1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-03 17:54:06 +00:00

added scriptrunning/startscript/stopscript; sorted out more case problems

This commit is contained in:
Marc Zinnschlag 2010-07-04 16:00:32 +02:00
parent 185f8bd56d
commit a61b2c39f0
26 changed files with 274 additions and 42 deletions

View File

@ -101,6 +101,15 @@ namespace SAInterpreter
void Context::setGlobalFloat (const std::string& name, float value) {}
bool Context::isScriptRunning (const std::string& name)
{
return false;
}
void Context::startScript (const std::string& name) {}
void Context::stopScript (const std::string& name) {}
void Context::report()
{
std::size_t i = 0;

View File

@ -52,6 +52,12 @@ namespace SAInterpreter
virtual void setGlobalFloat (const std::string& name, float value);
virtual bool isScriptRunning (const std::string& name);
virtual void startScript (const std::string& name);
virtual void stopScript (const std::string& name);
void report();
///< Write state to std::cout
};

View File

@ -42,7 +42,7 @@ bool OMW::Engine::frameStarted(const Ogre::FrameEvent& evt)
executeLocalScripts();
// global scripts
mGlobalScripts->run (mEnvironment);
mEnvironment.mGlobalScripts->run (mEnvironment);
return true;
}
@ -63,7 +63,7 @@ void OMW::Engine::processCommands()
}
OMW::Engine::Engine()
: mDebug (false), mVerboseScripts (false), mScriptManager (0), mGlobalScripts (0),
: mDebug (false), mVerboseScripts (false), mNewGame (false), mScriptManager (0),
mScriptContext (0)
{
mspCommandServer.reset(
@ -75,7 +75,7 @@ OMW::Engine::~Engine()
// mspCommandServer->stop();
delete mEnvironment.mWorld;
delete mEnvironment.mSoundManager;
delete mGlobalScripts;
delete mEnvironment.mGlobalScripts;
delete mScriptManager;
delete mScriptContext;
}
@ -146,6 +146,11 @@ void OMW::Engine::enableVerboseScripts()
mVerboseScripts = true;
}
void OMW::Engine::setNewGame()
{
mNewGame = true;
}
// Initialise and enter main loop.
void OMW::Engine::go()
@ -174,7 +179,7 @@ void OMW::Engine::go()
loadBSA();
// Create the world
mEnvironment.mWorld = new MWWorld::World (mOgre, mDataDir, mMaster, mCellName);
mEnvironment.mWorld = new MWWorld::World (mOgre, mDataDir, mMaster, mCellName, mNewGame);
mEnvironment.mSoundManager = new MWSound::SoundManager;
@ -187,7 +192,8 @@ void OMW::Engine::go()
mScriptManager = new MWScript::ScriptManager (mEnvironment.mWorld->getStore(), mVerboseScripts,
*mScriptContext);
mGlobalScripts = new MWScript::GlobalScripts (mEnvironment.mWorld->getStore(), *mScriptManager);
mEnvironment.mGlobalScripts = new MWScript::GlobalScripts (mEnvironment.mWorld->getStore(),
*mScriptManager);
std::cout << "Setting up input system\n";

View File

@ -23,7 +23,6 @@ namespace Compiler
namespace MWScript
{
class ScriptManager;
class GlobalScripts;
}
namespace MWSound
@ -50,13 +49,13 @@ namespace OMW
std::string mMaster;
bool mDebug;
bool mVerboseScripts;
bool mNewGame;
TsDeque<OMW::Command> mCommandQueue;
std::auto_ptr<OMW::CommandServer::Server> mspCommandServer;
MWWorld::Environment mEnvironment;
MWScript::ScriptManager *mScriptManager;
MWScript::GlobalScripts *mGlobalScripts;
Compiler::Extensions mExtensions;
Compiler::Context *mScriptContext;
@ -101,6 +100,9 @@ namespace OMW
/// Enable verbose script output
void enableVerboseScripts();
/// Start as a new game.
void setNewGame();
/// Initialise and enter main loop.
void go();

View File

@ -31,6 +31,7 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine)
"master file")
( "debug", "debug mode" )
( "script-verbose", "verbose script output" )
( "new-game", "activate char gen/new game mechanics" )
;
bpo::variables_map variables;
@ -59,6 +60,9 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine)
if (variables.count ("script-verbose"))
engine.enableVerboseScripts();
if (variables.count ("new-game"))
engine.setNewGame();
return true;
}

View File

@ -1,5 +1,8 @@
#include "globalscripts.hpp"
#include <cassert>
#include "interpretercontext.hpp"
#include "scriptmanager.hpp"
@ -25,22 +28,42 @@ namespace MWScript
locals.configure (*script);
mScripts.insert (std::make_pair (name, locals));
mScripts.insert (std::make_pair (name, std::make_pair (true, locals)));
}
}
void GlobalScripts::removeScript (const std::string& name)
{
std::map<std::string, std::pair<bool, Locals> >::iterator iter = mScripts.find (name);
if (iter!=mScripts.end())
iter->second.first = false;
}
bool GlobalScripts::isRunning (const std::string& name) const
{
std::map<std::string, std::pair<bool, Locals> >::const_iterator iter =
mScripts.find (name);
if (iter==mScripts.end())
return false;
return iter->second.first;
}
void GlobalScripts::run (MWWorld::Environment& environment)
{
std::map<std::string, Locals>::iterator iter = mScripts.begin();
while (iter!=mScripts.end())
for (std::map<std::string, std::pair<bool, Locals> >::iterator iter (mScripts.begin());
iter!=mScripts.end(); ++iter)
{
MWScript::InterpreterContext interpreterContext (environment,
&iter->second, MWWorld::Ptr());
mScriptManager.run (iter->first, interpreterContext);
++iter;
if (iter->second.first)
{
MWScript::InterpreterContext interpreterContext (environment,
&iter->second.second, MWWorld::Ptr());
mScriptManager.run (iter->first, interpreterContext);
}
}
}
}

View File

@ -24,7 +24,7 @@ namespace MWScript
{
const ESMS::ESMStore& mStore;
ScriptManager& mScriptManager;
std::map<std::string, Locals> mScripts;
std::map<std::string, std::pair<bool, Locals> > mScripts; // running, local variables
public:
@ -32,7 +32,12 @@ namespace MWScript
void addScript (const std::string& name);
void removeScript (const std::string& name);
bool isRunning (const std::string& name) const;
void run (MWWorld::Environment& environment);
///< run all active global scripts
};
}

View File

@ -6,12 +6,14 @@
#include <components/interpreter/types.hpp>
#include "locals.hpp"
#include "../mwworld/world.hpp"
#include "locals.hpp"
#include "globalscripts.hpp"
namespace MWScript
{
InterpreterContext::InterpreterContext (const MWWorld::Environment& environment,
InterpreterContext::InterpreterContext (MWWorld::Environment& environment,
MWScript::Locals *locals, MWWorld::Ptr reference)
: mEnvironment (environment), mLocals (locals), mReference (reference)
{}
@ -119,7 +121,22 @@ namespace MWScript
mEnvironment.mWorld->getGlobalVariable (name) =
*reinterpret_cast<Interpreter::Type_Data *> (&value);
}
bool InterpreterContext::isScriptRunning (const std::string& name)
{
return mEnvironment.mGlobalScripts->isRunning (name);
}
void InterpreterContext::startScript (const std::string& name)
{
mEnvironment.mGlobalScripts->addScript (name);
}
void InterpreterContext::stopScript (const std::string& name)
{
mEnvironment.mGlobalScripts->removeScript (name);
}
MWWorld::World& InterpreterContext::getWorld()
{
return *mEnvironment.mWorld;

View File

@ -22,13 +22,13 @@ namespace MWScript
class InterpreterContext : public Interpreter::Context
{
MWWorld::Environment mEnvironment;
MWWorld::Environment& mEnvironment;
Locals *mLocals;
MWWorld::Ptr mReference;
public:
InterpreterContext (const MWWorld::Environment& environment,
InterpreterContext (MWWorld::Environment& environment,
MWScript::Locals *locals, MWWorld::Ptr reference);
///< The ownership of \a locals is not transferred. 0-pointer allowed.
@ -61,6 +61,12 @@ namespace MWScript
virtual void setGlobalFloat (const std::string& name, float value);
virtual bool isScriptRunning (const std::string& name);
virtual void startScript (const std::string& name);
virtual void stopScript (const std::string& name);
MWWorld::World& getWorld();
MWSound::SoundManager& getSoundManager();

View File

@ -205,15 +205,15 @@ namespace MWSound
extensions.registerInstruction ("say", "SS", Script::opcodeSay);
extensions.registerFunction ("saydone", 'l', "", Script::opcodeSayDone);
extensions.registerInstruction ("streammusic", "S", Script::opcodeStreamMusic);
extensions.registerInstruction ("playsound", "S", Script::opcodePlaySound);
extensions.registerInstruction ("playsoundvp", "Sff", Script::opcodePlaySoundVP);
extensions.registerInstruction ("playsound3d", "S", Script::opcodePlaySound3D);
extensions.registerInstruction ("playsound3dvp", "Sff", Script::opcodePlaySound3DVP);
extensions.registerInstruction ("playloopsound3d", "S", Script::opcodePlayLoopSound3D);
extensions.registerInstruction ("playloopsound3dvp", "Sff",
extensions.registerInstruction ("playsound", "c", Script::opcodePlaySound);
extensions.registerInstruction ("playsoundvp", "cff", Script::opcodePlaySoundVP);
extensions.registerInstruction ("playsound3d", "c", Script::opcodePlaySound3D);
extensions.registerInstruction ("playsound3dvp", "cff", Script::opcodePlaySound3DVP);
extensions.registerInstruction ("playloopsound3d", "c", Script::opcodePlayLoopSound3D);
extensions.registerInstruction ("playloopsound3dvp", "cff",
Script::opcodePlayLoopSound3DVP);
extensions.registerInstruction ("stopsound", "S", Script::opcodeStopSound);
extensions.registerFunction ("getsoundplaying", 'l', "S", Script::opcodeGetSoundPlaying);
extensions.registerInstruction ("stopsound", "c", Script::opcodeStopSound);
extensions.registerFunction ("getsoundplaying", 'l', "c", Script::opcodeGetSoundPlaying);
}
void installOpcodes (Interpreter::Interpreter& interpreter)

View File

@ -6,6 +6,11 @@ namespace MWSound
class SoundManager;
}
namespace MWScript
{
class GlobalScripts;
}
namespace MWWorld
{
class World;
@ -13,10 +18,11 @@ namespace MWWorld
///< Collection of script-accessable sub-systems
struct Environment
{
Environment() : mWorld (0), mSoundManager (0) {}
Environment() : mWorld (0), mSoundManager (0), mGlobalScripts (0) {}
World *mWorld;
MWSound::SoundManager *mSoundManager;
MWSound::SoundManager *mSoundManager;
MWScript::GlobalScripts *mGlobalScripts;
};
}

View File

@ -57,7 +57,7 @@ namespace MWWorld
}
World::World (Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir,
const std::string& master, const std::string& startCell)
const std::string& master, const std::string& startCell, bool newGame)
: mSkyManager (0), mScene (renderer), mPlayerPos (mScene.getCamera())
{
boost::filesystem::path masterPath (dataDir);
@ -79,6 +79,14 @@ namespace MWWorld
iter != mStore.globals.list.end(); ++iter)
mGlobalVariables.insert (std::make_pair (iter->first, iter->second.value));
if (newGame)
{
// set new game mark
float newGameState = 1;
mGlobalVariables["chargenstate"] =
*reinterpret_cast<Interpreter::Type_Data *> (&newGameState);
}
std::cout << "\nSetting up cell rendering\n";
// This connects the cell data with the rendering scene.

View File

@ -62,7 +62,7 @@ namespace MWWorld
public:
World (Render::OgreRenderer& renderer, const boost::filesystem::path& master,
const std::string& dataDir, const std::string& startCell);
const std::string& dataDir, const std::string& startCell, bool newGame);
~World();

View File

@ -315,6 +315,17 @@ namespace Compiler
mNextOperand = false;
return true;
}
else if (keyword==Scanner::K_scriptrunning)
{
mTokenLoc = loc;
parseArguments ("c", scanner);
Generator::scriptRunning (mCode);
mOperands.push_back ('l');
mNextOperand = false;
return true;
}
else
{
// check for custom extensions
@ -492,9 +503,10 @@ namespace Compiler
for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end();
++iter)
{
if (*iter=='S')
if (*iter=='S' || *iter=='c')
{
stringParser.reset();
if (*iter=='c') stringParser.smashCase();
scanner.scan (stringParser);
if (invert)

View File

@ -94,7 +94,7 @@ namespace Compiler
std::vector<Interpreter::Type_Code>& code, bool invert = false);
///< Parse sequence of arguments specified by \a arguments.
/// \param arguments Each character represents one arguments ('l': integer,
/// 'f': float, 'S': string)
/// 'f': float, 'S': string, 'c': string (case smashed))
/// \param invert Store arguments in reverted order.
};
}

View File

@ -259,6 +259,21 @@ namespace
{
code.push_back (Compiler::Generator::segment5 (45));
}
void opScriptRunning (Compiler::Generator::CodeContainer& code)
{
code.push_back (Compiler::Generator::segment5 (46));
}
void opStartScript (Compiler::Generator::CodeContainer& code)
{
code.push_back (Compiler::Generator::segment5 (47));
}
void opStopScript (Compiler::Generator::CodeContainer& code)
{
code.push_back (Compiler::Generator::segment5 (48));
}
}
namespace Compiler
@ -635,6 +650,21 @@ namespace Compiler
{
opRandom (code);
}
void scriptRunning (CodeContainer& code)
{
opScriptRunning (code);
}
void startScript (CodeContainer& code)
{
opStartScript (code);
}
void stopScript (CodeContainer& code)
{
opStopScript (code);
}
}
}

View File

@ -100,6 +100,12 @@ namespace Compiler
const std::string& name);
void random (CodeContainer& code);
void scriptRunning (CodeContainer& code);
void startScript (CodeContainer& code);
void stopScript (CodeContainer& code);
}
}

View File

@ -145,6 +145,20 @@ namespace Compiler
Generator::exit (mCode);
mState = EndState;
return true;
case Scanner::K_startscript:
mExprParser.parseArguments ("c", scanner, mCode, true);
Generator::startScript (mCode);
mState = EndState;
return true;
case Scanner::K_stopscript:
mExprParser.parseArguments ("c", scanner, mCode, true);
Generator::stopScript (mCode);
mState = EndState;
return true;
}
// check for custom extensions

View File

@ -244,6 +244,7 @@ namespace Compiler
"getsquareroot",
"menumode",
"random",
"startscript", "stopscript", "scriptrunning",
0
};

View File

@ -50,7 +50,8 @@ namespace Compiler
K_set, K_to,
K_getsquareroot,
K_menumode,
K_random
K_random,
K_startscript, K_stopscript, K_scriptrunning
};
enum special

View File

@ -10,7 +10,7 @@
namespace Compiler
{
StringParser::StringParser (ErrorHandler& errorHandler, Context& context, Literals& literals)
: Parser (errorHandler, context), mLiterals (literals), mState (StartState)
: Parser (errorHandler, context), mLiterals (literals), mState (StartState), mSmashCase (false)
{
}
@ -20,7 +20,11 @@ namespace Compiler
{
if (mState==StartState || mState==CommaState)
{
Generator::pushString (mCode, mLiterals, name);
if (mSmashCase)
Generator::pushString (mCode, mLiterals, toLower (name));
else
Generator::pushString (mCode, mLiterals, name);
return false;
}
@ -47,6 +51,12 @@ namespace Compiler
{
mState = StartState;
mCode.clear();
mSmashCase = false;
}
void StringParser::smashCase()
{
mSmashCase = false;
}
}

View File

@ -21,6 +21,7 @@ namespace Compiler
Literals& mLiterals;
State mState;
std::vector<Interpreter::Type_Code> mCode;
bool mSmashCase;
public:
@ -38,8 +39,11 @@ namespace Compiler
void append (std::vector<Interpreter::Type_Code>& code);
///< Append code for parsed string.
void smashCase();
///< Transform all scanned strings to lower case
void reset();
///< Reset parser to clean state.
///< Reset parser to clean state (this includes the smashCase function).
};
}

View File

@ -45,7 +45,13 @@ namespace Interpreter
virtual void setGlobalLong (const std::string& name, int value) = 0;
virtual void setGlobalFloat (const std::string& name, float value) = 0;
virtual void setGlobalFloat (const std::string& name, float value) = 0;
virtual bool isScriptRunning (const std::string& name) = 0;
virtual void startScript (const std::string& name) = 0;
virtual void stopScript (const std::string& name) = 0;
};
}

View File

@ -104,6 +104,9 @@ op 42: replace stack[0] with global short stack[0]
op 43: replace stack[0] with global long stack[0]
op 44: replace stack[0] with global float stack[0]
op 45: replace stack[0] with a random integer value in the range [0, stack[0]-1]
opcodes 46-33554431 unused
op 46: replace stack[0] with 1, if global script stack[0] is running, 0 else
op 47: start script stack[0] and pop
op 48: stop script stack[0] and pop
opcodes 49-33554431 unused
opcodes 33554432-67108863 reserved for extensions

View File

@ -9,6 +9,7 @@
#include "mathopcodes.hpp"
#include "controlopcodes.hpp"
#include "miscopcodes.hpp"
#include "scriptopcodes.hpp"
namespace Interpreter
{
@ -86,6 +87,11 @@ namespace Interpreter
interpreter.installSegment3 (0, new OpMessageBox);
interpreter.installSegment5 (38, new OpMenuMode);
interpreter.installSegment5 (45, new OpRandom);
// script control
interpreter.installSegment5 (46, new OpScriptRunning);
interpreter.installSegment5 (47, new OpStartScript);
interpreter.installSegment5 (48, new OpStopScript);
}
}

View File

@ -0,0 +1,47 @@
#ifndef INTERPRETER_SCRIPTOPCODES_H_INCLUDED
#define INTERPRETER_SCRIPTOPCODES_H_INCLUDED
#include "opcodes.hpp"
#include "runtime.hpp"
#include "context.hpp"
namespace Interpreter
{
class OpScriptRunning : public Opcode0
{
public:
virtual void execute (Runtime& runtime)
{
std::string name = runtime.getStringLiteral (runtime[0]);
runtime[0] = runtime.getContext().isScriptRunning (name);
}
};
class OpStartScript : public Opcode0
{
public:
virtual void execute (Runtime& runtime)
{
std::string name = runtime.getStringLiteral (runtime[0]);
runtime.pop();
runtime.getContext().startScript (name);
}
};
class OpStopScript : public Opcode0
{
public:
virtual void execute (Runtime& runtime)
{
std::string name = runtime.getStringLiteral (runtime[0]);
runtime.pop();
runtime.getContext().stopScript (name);
}
};
}
#endif