mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:23:51 +00:00
Merge branch 'master' into exterior
Conflicts: apps/openmw/mwscript/docs/vmformat.txt
This commit is contained in:
commit
1dc805d0d4
54 changed files with 2419 additions and 1627 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,4 @@
|
|||
build
|
||||
*~
|
||||
Doxygen
|
||||
prebuilt
|
|
@ -8,6 +8,35 @@ option(USE_MPG123 "use mpg123 + libsndfile for sound" ON)
|
|||
# We probably support older versions than this.
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
|
||||
#
|
||||
# Pre-built binaries being used?
|
||||
#
|
||||
IF(EXISTS "${CMAKE_SOURCE_DIR}/prebuilt/vc100-mt-gd/ogre_1_7_1")
|
||||
set(PREBUILT_DIR "${CMAKE_SOURCE_DIR}/prebuilt/vc100-mt-gd")
|
||||
message (STATUS "OpenMW pre-built binaries found at ${PREBUILT_DIR}.")
|
||||
|
||||
SET(ENV{OGRE_HOME} "${PREBUILT_DIR}/ogre_1_7_1")
|
||||
|
||||
SET(ENV{BOOST_ROOT} "${PREBUILT_DIR}/boost_1_42_0")
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
set(ENV{BOOST_INCLUDEDIR} "${BOOST_ROOT}/include")
|
||||
set(ENV{BOOST_LIBRARYDIR} "${BOOST_ROOT}/lib")
|
||||
|
||||
set(ENV{FREETYPE_DIR} "${PREBUILT_DIR}/freetype-2.3.5-1")
|
||||
|
||||
set(USE_MPG123 OFF)
|
||||
set(USE_AUDIERE ON)
|
||||
set(AUDIERE_INCLUDE_DIR "${PREBUILT_DIR}/audiere-1.9.4/include")
|
||||
set(AUDIERE_LIBRARY "${PREBUILT_DIR}/audiere-1.9.4/lib/audiere.lib")
|
||||
|
||||
set(ENV{OPENALDIR} "${PREBUILT_DIR}/OpenAL 1.1 SDK")
|
||||
|
||||
ELSE()
|
||||
message (STATUS "OpenMW pre-built binaries not found. Using standard locations.")
|
||||
ENDIF()
|
||||
|
||||
# Add path for CMake scripts
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
|
||||
|
||||
|
@ -166,6 +195,9 @@ if (WIN32)
|
|||
else (WIN32)
|
||||
set(PLATFORM_INCLUDE_DIR "")
|
||||
endif (WIN32)
|
||||
if (MSVC10)
|
||||
set(PLATFORM_INCLUDE_DIR "")
|
||||
endif()
|
||||
|
||||
# Dependencies
|
||||
|
||||
|
@ -180,10 +212,10 @@ include_directories("."
|
|||
${CMAKE_HOME_DIRECTORY}/extern/caelum/include
|
||||
${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/MyGUIEngine/include
|
||||
${CMAKE_HOME_DIRECTORY}/extern/mygui_3.0.1/OgrePlatform/include
|
||||
${OPENAL_INCLUDE_DIR}
|
||||
${LIBDIR}
|
||||
)
|
||||
|
||||
|
||||
link_directories(${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR})
|
||||
|
||||
add_subdirectory( extern/caelum )
|
||||
|
@ -215,7 +247,7 @@ endif (APPLE)
|
|||
|
||||
# Compiler settings
|
||||
if (CMAKE_COMPILER_IS_GNUCC)
|
||||
add_definitions (-Wall)
|
||||
add_definitions (-Wall -Werror)
|
||||
endif (CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
# Apple bundling
|
||||
|
|
|
@ -573,10 +573,10 @@ WARN_LOGFILE =
|
|||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = ..\apps
|
||||
..\components
|
||||
..\libs
|
||||
..\docs
|
||||
INPUT = ../apps
|
||||
../components
|
||||
../libs
|
||||
../docs
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||
|
@ -1372,7 +1372,7 @@ HIDE_UNDOC_RELATIONS = YES
|
|||
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
|
||||
# have no effect if this option is set to NO (the default)
|
||||
|
||||
HAVE_DOT = NO
|
||||
HAVE_DOT = YES
|
||||
|
||||
# By default doxygen will write a font called FreeSans.ttf to the output
|
||||
# directory and reference it in all dot files that doxygen generates. This
|
||||
|
@ -1420,7 +1420,7 @@ GROUP_GRAPHS = YES
|
|||
# collaboration diagrams in a style similar to the OMG's Unified Modeling
|
||||
# Language.
|
||||
|
||||
UML_LOOK = NO
|
||||
UML_LOOK = YES
|
||||
|
||||
# If set to YES, the inheritance and collaboration graphs will show the
|
||||
# relations between templates and their instances.
|
||||
|
|
|
@ -10,6 +10,7 @@ add_executable(esmtool
|
|||
${ESMTOOL}
|
||||
${MISC} ${MISC_HEADER}
|
||||
${TO_UTF8}
|
||||
${ESM}
|
||||
)
|
||||
|
||||
target_link_libraries(esmtool
|
||||
|
|
|
@ -63,6 +63,8 @@ set(GAMESCRIPT
|
|||
mwscript/skyextensions.cpp
|
||||
mwscript/statsextensions.cpp
|
||||
mwscript/containerextensions.cpp
|
||||
mwscript/aiextensions.cpp
|
||||
mwscript/controlextensions.cpp
|
||||
mwscript/extensions.cpp
|
||||
mwscript/globalscripts.cpp
|
||||
)
|
||||
|
@ -78,6 +80,8 @@ set(GAMESCRIPT_HEADER
|
|||
mwscript/skyextensions.hpp
|
||||
mwscript/statsextensions.hpp
|
||||
mwscript/containerextensions.hpp
|
||||
mwscript/aiextensions.hpp
|
||||
mwscript/controlextensions.hpp
|
||||
mwscript/extensions.hpp
|
||||
mwscript/globalscripts.hpp
|
||||
)
|
||||
|
@ -204,7 +208,7 @@ target_link_libraries(openmw
|
|||
${SOUND_INPUT_LIBRARY}
|
||||
caelum
|
||||
MyGUIEngine
|
||||
MyGUI.OgrePlatform
|
||||
MyGUIOgrePlatform
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
|
|
|
@ -109,6 +109,7 @@ OMW::Engine::Engine()
|
|||
, mUseSound (true)
|
||||
, mScriptManager (0)
|
||||
, mScriptContext (0)
|
||||
, mGuiManager (0)
|
||||
{
|
||||
MWClass::registerClasses();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#include "../mwrender/cellimp.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
void Door::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
|
||||
|
@ -50,6 +52,16 @@ namespace MWClass
|
|||
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
|
||||
ptr.get<ESM::Door>();
|
||||
|
||||
if (ptr.getCellRef().lockLevel>0)
|
||||
{
|
||||
// TODO check for key
|
||||
// TODO report failure to player (message, sound?). Look up behaviour of original MW.
|
||||
std::cout << "Locked!" << std::endl;
|
||||
return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction);
|
||||
}
|
||||
|
||||
// TODO check trap
|
||||
|
||||
if (ref->ref.teleport)
|
||||
{
|
||||
// teleport door
|
||||
|
@ -74,6 +86,19 @@ namespace MWClass
|
|||
}
|
||||
}
|
||||
|
||||
void Door::lock (const MWWorld::Ptr& ptr, int lockLevel) const
|
||||
{
|
||||
if (lockLevel<0)
|
||||
lockLevel = 0;
|
||||
|
||||
ptr.getCellRef().lockLevel = lockLevel;
|
||||
}
|
||||
|
||||
void Door::unlock (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ptr.getCellRef().lockLevel = 0;
|
||||
}
|
||||
|
||||
std::string Door::getScript (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ESMS::LiveCellRef<ESM::Door, MWWorld::RefData> *ref =
|
||||
|
|
|
@ -21,6 +21,12 @@ namespace MWClass
|
|||
const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const;
|
||||
///< Generate action for activation
|
||||
|
||||
virtual void lock (const MWWorld::Ptr& ptr, int lockLevel) const;
|
||||
///< Lock object
|
||||
|
||||
virtual void unlock (const MWWorld::Ptr& ptr) const;
|
||||
///< Unlock object
|
||||
|
||||
virtual std::string getScript (const MWWorld::Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr
|
||||
|
||||
|
|
|
@ -15,9 +15,6 @@ namespace MWGui
|
|||
|
||||
ConsoleInterpreterContext (Console& console, MWWorld::Environment& environment,
|
||||
MWWorld::Ptr reference);
|
||||
|
||||
virtual void messageBox (const std::string& message,
|
||||
const std::vector<std::string>& buttons);
|
||||
};
|
||||
|
||||
ConsoleInterpreterContext::ConsoleInterpreterContext (Console& console,
|
||||
|
@ -27,15 +24,6 @@ namespace MWGui
|
|||
mConsole (console)
|
||||
{}
|
||||
|
||||
void ConsoleInterpreterContext::messageBox (const std::string& message,
|
||||
const std::vector<std::string>& buttons)
|
||||
{
|
||||
if (!buttons.empty())
|
||||
mConsole.printError ("MessageBox doesn't support buttons while in console mode");
|
||||
else
|
||||
mConsole.printOK (message);
|
||||
}
|
||||
|
||||
bool Console::compile (const std::string& cmd, Compiler::Output& output)
|
||||
{
|
||||
try
|
||||
|
@ -196,7 +184,7 @@ namespace MWGui
|
|||
Compiler::Locals locals;
|
||||
Compiler::Output output (locals);
|
||||
|
||||
if (compile (cm, output))
|
||||
if (compile (cm + "\n", output))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -216,4 +204,3 @@ namespace MWGui
|
|||
command->setCaption("");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "console.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
|
@ -13,8 +15,8 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment
|
|||
{
|
||||
// Get size info from the Gui object
|
||||
assert(gui);
|
||||
int w = gui->getViewWidth();
|
||||
int h = gui->getViewHeight();
|
||||
int w = gui->getViewSize().width;
|
||||
int h = gui->getViewSize().height;
|
||||
|
||||
hud = new HUD(w,h);
|
||||
menu = new MainMenu(w,h);
|
||||
|
@ -95,3 +97,15 @@ void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicS
|
|||
stats->setValue (id, value);
|
||||
hud->setValue (id, value);
|
||||
}
|
||||
|
||||
void WindowManager::messageBox (const std::string& message, const std::vector<std::string>& buttons)
|
||||
{
|
||||
std::cout << "message box: " << message << std::endl;
|
||||
|
||||
if (!buttons.empty())
|
||||
{
|
||||
std::cout << "buttons: ";
|
||||
std::copy (buttons.begin(), buttons.end(), std::ostream_iterator<std::string> (std::cout, ", "));
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "../mwmechanics/stat.hpp"
|
||||
|
||||
|
@ -144,6 +145,8 @@ namespace MWGui
|
|||
|
||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<int>& value);
|
||||
///< Set value for the given ID.
|
||||
|
||||
void messageBox (const std::string& message, const std::vector<std::string>& buttons);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
|
215
apps/openmw/mwscript/aiextensions.cpp
Normal file
215
apps/openmw/mwscript/aiextensions.cpp
Normal file
|
@ -0,0 +1,215 @@
|
|||
|
||||
#include "aiextensions.hpp"
|
||||
|
||||
#include <components/compiler/extensions.hpp>
|
||||
|
||||
#include <components/interpreter/interpreter.hpp>
|
||||
#include <components/interpreter/runtime.hpp>
|
||||
#include <components/interpreter/opcodes.hpp>
|
||||
|
||||
#include "interpretercontext.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
namespace Ai
|
||||
{
|
||||
class OpAiTravel : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
MWWorld::Ptr ptr = context.getReference();
|
||||
|
||||
Interpreter::Type_Float x = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float y = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float z = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
// discard additional arguments (reset), because we have no idea what they mean.
|
||||
for (unsigned int i=0; i<arg0; ++i) runtime.pop();
|
||||
|
||||
std::cout << "AiTravel: " << x << ", " << y << ", " << z << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
class OpAiTravelExplicit : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr ptr = context.getWorld().getPtr (id, false);
|
||||
|
||||
Interpreter::Type_Float x = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float y = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float z = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
// discard additional arguments (reset), because we have no idea what they mean.
|
||||
for (unsigned int i=0; i<arg0; ++i) runtime.pop();
|
||||
|
||||
std::cout << "AiTravel: " << x << ", " << y << ", " << z << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
class OpAiEscort : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr ptr = context.getReference();
|
||||
|
||||
std::string actor = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float duration = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float x = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float y = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float z = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
// discard additional arguments (reset), because we have no idea what they mean.
|
||||
for (unsigned int i=0; i<arg0; ++i) runtime.pop();
|
||||
|
||||
std::cout << "AiEscort: " << x << ", " << y << ", " << z << ", " << duration
|
||||
<< std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
class OpAiEscortExplicit : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr ptr = context.getWorld().getPtr (id, false);
|
||||
|
||||
std::string actor = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float duration = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float x = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float y = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
Interpreter::Type_Float z = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
// discard additional arguments (reset), because we have no idea what they mean.
|
||||
for (unsigned int i=0; i<arg0; ++i) runtime.pop();
|
||||
|
||||
std::cout << "AiEscort: " << x << ", " << y << ", " << z << ", " << duration
|
||||
<< std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
class OpGetAiPackageDone : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
MWWorld::Ptr ptr = context.getReference();
|
||||
|
||||
Interpreter::Type_Integer value = 0;
|
||||
|
||||
runtime.push (value);
|
||||
}
|
||||
};
|
||||
|
||||
class OpGetAiPackageDoneExplicit : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWScript::InterpreterContext& context
|
||||
= static_cast<MWScript::InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr ptr = context.getWorld().getPtr (id, false);
|
||||
|
||||
Interpreter::Type_Integer value = 0;
|
||||
|
||||
runtime.push (value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const int opcodeAiTravel = 0x20000;
|
||||
const int opcodeAiTravelExplicit = 0x20001;
|
||||
const int opcodeAiEscort = 0x20002;
|
||||
const int opcodeAiEscortExplicit = 0x20003;
|
||||
const int opcodeGetAiPackageDone = 0x200007c;
|
||||
const int opcodeGetAiPackageDoneExplicit = 0x200007d;
|
||||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
extensions.registerInstruction ("aitravel", "lll/l", opcodeAiTravel,
|
||||
opcodeAiTravelExplicit);
|
||||
extensions.registerInstruction ("aiescort", "cllll/l", opcodeAiEscort,
|
||||
opcodeAiEscortExplicit);
|
||||
|
||||
extensions.registerFunction ("getaipackagedone", 'l', "", opcodeGetAiPackageDone,
|
||||
opcodeGetAiPackageDoneExplicit);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
{
|
||||
interpreter.installSegment3 (opcodeAiTravel, new OpAiTravel);
|
||||
interpreter.installSegment3 (opcodeAiTravelExplicit, new OpAiTravelExplicit);
|
||||
interpreter.installSegment3 (opcodeAiEscort, new OpAiEscort);
|
||||
interpreter.installSegment3 (opcodeAiEscortExplicit, new OpAiEscortExplicit);
|
||||
interpreter.installSegment5 (opcodeGetAiPackageDone, new OpGetAiPackageDone);
|
||||
interpreter.installSegment5 (opcodeGetAiPackageDoneExplicit, new OpGetAiPackageDoneExplicit);
|
||||
}
|
||||
}
|
||||
}
|
25
apps/openmw/mwscript/aiextensions.hpp
Normal file
25
apps/openmw/mwscript/aiextensions.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef GAME_SCRIPT_AIEXTENSIONS_H
|
||||
#define GAME_SCRIPT_AIEXTENSIONS_H
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
class Extensions;
|
||||
}
|
||||
|
||||
namespace Interpreter
|
||||
{
|
||||
class Interpreter;
|
||||
}
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
/// \brief AI-related script functionality
|
||||
namespace Ai
|
||||
{
|
||||
void registerExtensions (Compiler::Extensions& extensions);
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
70
apps/openmw/mwscript/controlextensions.cpp
Normal file
70
apps/openmw/mwscript/controlextensions.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
|
||||
#include "statsextensions.hpp"
|
||||
|
||||
#include <components/compiler/extensions.hpp>
|
||||
|
||||
#include <components/interpreter/interpreter.hpp>
|
||||
#include <components/interpreter/runtime.hpp>
|
||||
#include <components/interpreter/opcodes.hpp>
|
||||
|
||||
#include "interpretercontext.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
namespace Control
|
||||
{
|
||||
class OpSetControl : public Interpreter::Opcode0
|
||||
{
|
||||
std::string mControl;
|
||||
bool mEnable;
|
||||
|
||||
public:
|
||||
|
||||
OpSetControl (const std::string& control, bool enable)
|
||||
: mControl (control), mEnable (enable)
|
||||
{}
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
if (mEnable)
|
||||
std::cout << "enable: " << mControl << std::endl;
|
||||
else
|
||||
std::cout << "disable: " << mControl << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
const int numberOfControls = 7;
|
||||
|
||||
const int opcodeEnable = 0x200007e;
|
||||
const int opcodeDisable = 0x2000085;
|
||||
|
||||
const char *controls[numberOfControls] =
|
||||
{
|
||||
"playercontrols", "playerfighting", "playerjumping", "playerlooking", "playermagic",
|
||||
"playerviewswitch", "vanitymode"
|
||||
};
|
||||
|
||||
void registerExtensions (Compiler::Extensions& extensions)
|
||||
{
|
||||
std::string enable ("enable");
|
||||
std::string disable ("disable");
|
||||
|
||||
for (int i=0; i<numberOfControls; ++i)
|
||||
{
|
||||
extensions.registerInstruction (enable + controls[i], "", opcodeEnable+i);
|
||||
extensions.registerInstruction (disable + controls[i], "", opcodeDisable+i);
|
||||
}
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
{
|
||||
for (int i=0; i<numberOfControls; ++i)
|
||||
{
|
||||
interpreter.installSegment5 (opcodeEnable+i, new OpSetControl (controls[i], true));
|
||||
interpreter.installSegment5 (opcodeDisable+i, new OpSetControl (controls[i], false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
apps/openmw/mwscript/controlextensions.hpp
Normal file
25
apps/openmw/mwscript/controlextensions.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef GAME_SCRIPT_CONTROLEXTENSIONS_H
|
||||
#define GAME_SCRIPT_CONTROLEXTENSIONS_H
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
class Extensions;
|
||||
}
|
||||
|
||||
namespace Interpreter
|
||||
{
|
||||
class Interpreter;
|
||||
}
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
/// \brief player controls-related script functionality
|
||||
namespace Control
|
||||
{
|
||||
void registerExtensions (Compiler::Extensions& extensions);
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -13,8 +13,13 @@ Segment 2:
|
|||
opcodes 0x200-0x3ff unused
|
||||
|
||||
Segment 3:
|
||||
(not implemented yet)
|
||||
opcodes 0x200-0x3ff unused
|
||||
op 0x20000: AiTravel
|
||||
op 0x20001: AiTravel, explicit reference
|
||||
op 0x20002: AiEscort
|
||||
op 0x20003: AiEscort, explicit reference
|
||||
op 0x20004: Lock
|
||||
op 0x20005: Lock, explicit reference
|
||||
opcodes 0x20006-0x3ffff unused
|
||||
|
||||
Segment 4:
|
||||
(not implemented yet)
|
||||
|
@ -83,5 +88,15 @@ op 0x2000078: GetItemCount
|
|||
op 0x2000079: GetItemCount, explicit reference
|
||||
op 0x200007a: RemoveItem
|
||||
op 0x200007b: RemoveItem, explicit reference
|
||||
<<<<<<< HEAD:apps/openmw/mwscript/docs/vmformat.txt
|
||||
op 0x200007c: COC
|
||||
opcodes 0x200007d-0x3ffffff unused
|
||||
=======
|
||||
op 0x200007c: GetAiPackageDone
|
||||
op 0x200007d: GetAiPackageDone, explicit reference
|
||||
op 0x200007e-0x2000084: Enable Controls
|
||||
op 0x2000085-0x200008b: Disable Controls
|
||||
op 0x200008c: Unlock
|
||||
op 0x200008d: Unlock, explicit reference
|
||||
opcodes 0x200008e-0x3ffffff unused
|
||||
>>>>>>> master:apps/openmw/mwscript/docs/vmformat.txt
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "skyextensions.hpp"
|
||||
#include "statsextensions.hpp"
|
||||
#include "containerextensions.hpp"
|
||||
#include "aiextensions.hpp"
|
||||
#include "controlextensions.hpp"
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
|
@ -23,6 +25,8 @@ namespace MWScript
|
|||
Sky::registerExtensions (extensions);
|
||||
Stats::registerExtensions (extensions);
|
||||
Container::registerExtensions (extensions);
|
||||
Ai::registerExtensions (extensions);
|
||||
Control::registerExtensions (extensions);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
|
@ -35,5 +39,7 @@ namespace MWScript
|
|||
Sky::installOpcodes (interpreter);
|
||||
Stats::installOpcodes (interpreter);
|
||||
Container::installOpcodes (interpreter);
|
||||
Ai::installOpcodes (interpreter);
|
||||
Control::installOpcodes (interpreter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,10 +105,7 @@ namespace MWScript
|
|||
void InterpreterContext::messageBox (const std::string& message,
|
||||
const std::vector<std::string>& buttons)
|
||||
{
|
||||
std::cout << "message box: " << message << std::endl;
|
||||
|
||||
if (!buttons.empty())
|
||||
std::cerr << "error: message box buttons not supported" << std::endl;
|
||||
mEnvironment.mWindowManager->messageBox (message, buttons);
|
||||
}
|
||||
|
||||
bool InterpreterContext::menuMode()
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include "interpretercontext.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
namespace Misc
|
||||
|
@ -53,15 +55,104 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
class OpLock : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
MWWorld::Ptr ptr = context.getReference();
|
||||
|
||||
Interpreter::Type_Integer lockLevel = 100;
|
||||
|
||||
if (arg0==1)
|
||||
{
|
||||
lockLevel = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
}
|
||||
|
||||
MWWorld::Class::get (ptr).lock (ptr, lockLevel);
|
||||
}
|
||||
};
|
||||
|
||||
class OpLockExplicit : public Interpreter::Opcode1
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr ptr = context.getWorld().getPtr (id, false);
|
||||
|
||||
Interpreter::Type_Integer lockLevel = 100;
|
||||
|
||||
if (arg0==1)
|
||||
{
|
||||
lockLevel = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
}
|
||||
|
||||
MWWorld::Class::get (ptr).lock (ptr, lockLevel);
|
||||
}
|
||||
};
|
||||
|
||||
class OpUnlock : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
MWWorld::Ptr ptr = context.getReference();
|
||||
|
||||
MWWorld::Class::get (ptr).unlock (ptr);
|
||||
}
|
||||
};
|
||||
|
||||
class OpUnlockExplicit : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
InterpreterContext& context =
|
||||
static_cast<InterpreterContext&> (runtime.getContext());
|
||||
|
||||
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr ptr = context.getWorld().getPtr (id, false);
|
||||
|
||||
MWWorld::Class::get (ptr).unlock (ptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
|
@ -69,6 +160,10 @@ namespace MWScript
|
|||
interpreter.installSegment5 (opcodeXBox, new OpXBox);
|
||||
interpreter.installSegment5 (opcodeOnActivate, new OpOnActivate);
|
||||
interpreter.installSegment5 (opcodeActivate, new OpActivate);
|
||||
interpreter.installSegment3 (opcodeLock, new OpLock);
|
||||
interpreter.installSegment3 (opcodeLockExplicit, new OpLockExplicit);
|
||||
interpreter.installSegment5 (opcodeUnlock, new OpUnlock);
|
||||
interpreter.installSegment5 (opcodeUnlockExplicit, new OpUnlockExplicit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace MWScript
|
|||
if (!mErrorHandler.isGood())
|
||||
Success = false;
|
||||
}
|
||||
catch (const std::exception& error)
|
||||
catch (...)
|
||||
{
|
||||
Success = false;
|
||||
}
|
||||
|
@ -114,4 +114,3 @@ namespace MWScript
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,6 +104,12 @@ namespace MWSound
|
|||
root->addFrameListener(&updater);
|
||||
}
|
||||
|
||||
~SoundImpl()
|
||||
{
|
||||
Ogre::Root::getSingleton().removeFrameListener(&updater);
|
||||
cameraTracker.unfollowCamera();
|
||||
}
|
||||
|
||||
std::string toMp3(const std::string &str)
|
||||
{
|
||||
std::string wav = str;
|
||||
|
@ -147,10 +153,10 @@ namespace MWSound
|
|||
const ESM::Sound *snd = store.sounds.search(soundId);
|
||||
if(snd == NULL) return "";
|
||||
|
||||
volume *= snd->data.volume / 255.0;
|
||||
volume *= snd->data.volume / 255.0f;
|
||||
// These factors are not very fine tuned.
|
||||
min = snd->data.minRange * 7;
|
||||
max = snd->data.maxRange * 2000;
|
||||
min = snd->data.minRange * 7.0f;
|
||||
max = snd->data.maxRange * 2000.0f;
|
||||
return convertPath(snd->sound);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace MWWorld
|
|||
: mCellName (cellName), mPosition (position)
|
||||
{}
|
||||
|
||||
void ActionTeleportPlayer::ActionTeleportPlayer::execute (Environment& environment)
|
||||
void ActionTeleportPlayer::execute (Environment& environment)
|
||||
{
|
||||
if (mCellName.empty())
|
||||
environment.mWorld->changeToExteriorCell (mPosition);
|
||||
|
|
|
@ -77,6 +77,16 @@ namespace MWWorld
|
|||
throw std::runtime_error ("class does not support inserting into a container");
|
||||
}
|
||||
|
||||
void Class::lock (const Ptr& ptr, int lockLevel) const
|
||||
{
|
||||
throw std::runtime_error ("class does not support locking");
|
||||
}
|
||||
|
||||
void Class::unlock (const Ptr& ptr) const
|
||||
{
|
||||
throw std::runtime_error ("class does not support unlocking");
|
||||
}
|
||||
|
||||
std::string Class::getScript (const Ptr& ptr) const
|
||||
{
|
||||
return "";
|
||||
|
|
|
@ -98,6 +98,12 @@ namespace MWWorld
|
|||
///< Insert into a container or throw an exception, if class does not support inserting into
|
||||
/// a container.
|
||||
|
||||
virtual void lock (const Ptr& ptr, int lockLevel) const;
|
||||
///< Lock object (default implementation: throw an exception)
|
||||
|
||||
virtual void unlock (const Ptr& ptr) const;
|
||||
///< Unlock object (default implementation: throw an exception)
|
||||
|
||||
virtual std::string getScript (const Ptr& ptr) const;
|
||||
///< Return name of the script attached to ptr (default implementation: return an empty
|
||||
/// string).
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
#include <libs/mangle/stream/servers/file_stream.hpp>
|
||||
#include <libs/mangle/stream/filters/slice_stream.hpp>
|
||||
#include <libs/mangle/tools/str_exception.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
@ -36,7 +36,7 @@ using namespace Mangle::Stream;
|
|||
/// Error handling
|
||||
void BSAFile::fail(const string &msg)
|
||||
{
|
||||
throw str_exception("BSA Error: " + msg + "\nArchive: " + filename);
|
||||
throw std::runtime_error("BSA Error: " + msg + "\nArchive: " + filename);
|
||||
}
|
||||
|
||||
/// Read header information from the input source
|
||||
|
|
|
@ -172,6 +172,20 @@ namespace Compiler
|
|||
std::copy (mCode.begin(), mCode.end(), std::back_inserter (code));
|
||||
}
|
||||
|
||||
bool ControlParser::parseName (const std::string& name, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (mState==IfBodyState || mState==IfElseifBodyState || mState==IfElseBodyState ||
|
||||
mState==WhileBodyState)
|
||||
{
|
||||
scanner.putbackName (name, loc);
|
||||
mLineParser.reset();
|
||||
scanner.scan (mLineParser);
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parser::parseName (name, loc, scanner);
|
||||
}
|
||||
|
||||
bool ControlParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
if (mState==StartState)
|
||||
|
@ -245,6 +259,6 @@ namespace Compiler
|
|||
mCodeBlock.clear();
|
||||
mIfCode.clear();
|
||||
mState = StartState;
|
||||
Parser::reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,11 @@ namespace Compiler
|
|||
void appendCode (std::vector<Interpreter::Type_Code>& code) const;
|
||||
///< store generated code in \æ code.
|
||||
|
||||
virtual bool parseName (const std::string& name, const TokenLoc& loc,
|
||||
Scanner& scanner);
|
||||
///< Handle a name token.
|
||||
/// \return fetch another token?
|
||||
|
||||
virtual bool parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner);
|
||||
///< Handle a keyword token.
|
||||
/// \return fetch another token?
|
||||
|
@ -67,4 +72,3 @@ namespace Compiler
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -190,9 +190,9 @@ namespace Compiler
|
|||
popOperator();
|
||||
}
|
||||
|
||||
void ExprParser::parseArguments (const std::string& arguments, Scanner& scanner)
|
||||
int ExprParser::parseArguments (const std::string& arguments, Scanner& scanner)
|
||||
{
|
||||
parseArguments (arguments, scanner, mCode);
|
||||
return parseArguments (arguments, scanner, mCode);
|
||||
}
|
||||
|
||||
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||
|
@ -210,6 +210,8 @@ namespace Compiler
|
|||
|
||||
if (mNextOperand)
|
||||
{
|
||||
start();
|
||||
|
||||
pushIntegerLiteral (value);
|
||||
mTokenLoc = loc;
|
||||
return true;
|
||||
|
@ -231,6 +233,8 @@ namespace Compiler
|
|||
|
||||
if (mNextOperand)
|
||||
{
|
||||
start();
|
||||
|
||||
pushFloatLiteral (value);
|
||||
mTokenLoc = loc;
|
||||
return true;
|
||||
|
@ -253,6 +257,8 @@ namespace Compiler
|
|||
|
||||
if (mNextOperand)
|
||||
{
|
||||
start();
|
||||
|
||||
std::string name2 = toLower (name);
|
||||
|
||||
char type = mLocals.getType (name2);
|
||||
|
@ -301,6 +307,8 @@ namespace Compiler
|
|||
{
|
||||
if (keyword==Scanner::K_getdisabled)
|
||||
{
|
||||
start();
|
||||
|
||||
mTokenLoc = loc;
|
||||
|
||||
Generator::getDisabled (mCode, mLiterals, mExplicit);
|
||||
|
@ -313,6 +321,8 @@ namespace Compiler
|
|||
}
|
||||
else if (keyword==Scanner::K_getdistance)
|
||||
{
|
||||
start();
|
||||
|
||||
mTokenLoc = loc;
|
||||
parseArguments ("c", scanner);
|
||||
|
||||
|
@ -333,10 +343,13 @@ namespace Compiler
|
|||
|
||||
if (extensions->isFunction (keyword, returnType, argumentType, true))
|
||||
{
|
||||
mTokenLoc = loc;
|
||||
parseArguments (argumentType, scanner);
|
||||
start();
|
||||
|
||||
extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit);
|
||||
mTokenLoc = loc;
|
||||
int optionals = parseArguments (argumentType, scanner);
|
||||
|
||||
extensions->generateFunctionCode (keyword, mCode, mLiterals, mExplicit,
|
||||
optionals);
|
||||
mOperands.push_back (returnType);
|
||||
mExplicit.clear();
|
||||
mRefOp = false;
|
||||
|
@ -354,6 +367,8 @@ namespace Compiler
|
|||
{
|
||||
if (keyword==Scanner::K_getsquareroot)
|
||||
{
|
||||
start();
|
||||
|
||||
mTokenLoc = loc;
|
||||
parseArguments ("f", scanner);
|
||||
|
||||
|
@ -365,6 +380,8 @@ namespace Compiler
|
|||
}
|
||||
else if (keyword==Scanner::K_menumode)
|
||||
{
|
||||
start();
|
||||
|
||||
mTokenLoc = loc;
|
||||
|
||||
Generator::menuMode (mCode);
|
||||
|
@ -375,6 +392,8 @@ namespace Compiler
|
|||
}
|
||||
else if (keyword==Scanner::K_random)
|
||||
{
|
||||
start();
|
||||
|
||||
mTokenLoc = loc;
|
||||
parseArguments ("l", scanner);
|
||||
|
||||
|
@ -386,6 +405,8 @@ namespace Compiler
|
|||
}
|
||||
else if (keyword==Scanner::K_scriptrunning)
|
||||
{
|
||||
start();
|
||||
|
||||
mTokenLoc = loc;
|
||||
parseArguments ("c", scanner);
|
||||
|
||||
|
@ -397,6 +418,8 @@ namespace Compiler
|
|||
}
|
||||
else if (keyword==Scanner::K_getdistance)
|
||||
{
|
||||
start();
|
||||
|
||||
mTokenLoc = loc;
|
||||
parseArguments ("c", scanner);
|
||||
|
||||
|
@ -408,6 +431,8 @@ namespace Compiler
|
|||
}
|
||||
else if (keyword==Scanner::K_getsecondspassed)
|
||||
{
|
||||
start();
|
||||
|
||||
mTokenLoc = loc;
|
||||
|
||||
Generator::getSecondsPassed (mCode);
|
||||
|
@ -418,6 +443,8 @@ namespace Compiler
|
|||
}
|
||||
else if (keyword==Scanner::K_getdisabled)
|
||||
{
|
||||
start();
|
||||
|
||||
mTokenLoc = loc;
|
||||
|
||||
Generator::getDisabled (mCode, mLiterals, "");
|
||||
|
@ -431,15 +458,17 @@ namespace Compiler
|
|||
// check for custom extensions
|
||||
if (const Extensions *extensions = getContext().getExtensions())
|
||||
{
|
||||
start();
|
||||
|
||||
char returnType;
|
||||
std::string argumentType;
|
||||
|
||||
if (extensions->isFunction (keyword, returnType, argumentType, false))
|
||||
{
|
||||
mTokenLoc = loc;
|
||||
parseArguments (argumentType, scanner);
|
||||
int optionals = parseArguments (argumentType, scanner);
|
||||
|
||||
extensions->generateFunctionCode (keyword, mCode, mLiterals, "");
|
||||
extensions->generateFunctionCode (keyword, mCode, mLiterals, "", optionals);
|
||||
mOperands.push_back (returnType);
|
||||
|
||||
mNextOperand = false;
|
||||
|
@ -580,6 +609,7 @@ namespace Compiler
|
|||
mFirst = true;
|
||||
mExplicit.clear();
|
||||
mRefOp = false;
|
||||
Parser::reset();
|
||||
}
|
||||
|
||||
char ExprParser::append (std::vector<Interpreter::Type_Code>& code)
|
||||
|
@ -605,9 +635,12 @@ namespace Compiler
|
|||
return mOperands[0];
|
||||
}
|
||||
|
||||
void ExprParser::parseArguments (const std::string& arguments, Scanner& scanner,
|
||||
int ExprParser::parseArguments (const std::string& arguments, Scanner& scanner,
|
||||
std::vector<Interpreter::Type_Code>& code, bool invert)
|
||||
{
|
||||
bool optional = false;
|
||||
bool optionalCount = 0;
|
||||
|
||||
ExprParser parser (getErrorHandler(), getContext(), mLocals, mLiterals, true);
|
||||
StringParser stringParser (getErrorHandler(), getContext(), mLiterals);
|
||||
|
||||
|
@ -616,12 +649,23 @@ namespace Compiler
|
|||
for (std::string::const_iterator iter (arguments.begin()); iter!=arguments.end();
|
||||
++iter)
|
||||
{
|
||||
if (*iter=='S' || *iter=='c')
|
||||
if (*iter=='/')
|
||||
{
|
||||
optional = true;
|
||||
}
|
||||
else if (*iter=='S' || *iter=='c')
|
||||
{
|
||||
stringParser.reset();
|
||||
|
||||
if (optional)
|
||||
stringParser.setOptional (true);
|
||||
|
||||
if (*iter=='c') stringParser.smashCase();
|
||||
scanner.scan (stringParser);
|
||||
|
||||
if (optional && stringParser.isEmpty())
|
||||
break;
|
||||
|
||||
if (invert)
|
||||
{
|
||||
std::vector<Interpreter::Type_Code> tmp;
|
||||
|
@ -631,12 +675,22 @@ namespace Compiler
|
|||
}
|
||||
else
|
||||
stringParser.append (code);
|
||||
|
||||
if (optional)
|
||||
++optionalCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.reset();
|
||||
|
||||
if (optional)
|
||||
parser.setOptional (true);
|
||||
|
||||
scanner.scan (parser);
|
||||
|
||||
if (optional && parser.isEmpty())
|
||||
break;
|
||||
|
||||
std::vector<Interpreter::Type_Code> tmp;
|
||||
|
||||
char type = parser.append (tmp);
|
||||
|
@ -648,6 +702,9 @@ namespace Compiler
|
|||
stack.push (tmp);
|
||||
else
|
||||
std::copy (tmp.begin(), tmp.end(), std::back_inserter (code));
|
||||
|
||||
if (optional)
|
||||
++optionalCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -659,6 +716,7 @@ namespace Compiler
|
|||
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
return optionalCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace Compiler
|
|||
|
||||
void close();
|
||||
|
||||
void parseArguments (const std::string& arguments, Scanner& scanner);
|
||||
int parseArguments (const std::string& arguments, Scanner& scanner);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -92,12 +92,14 @@ namespace Compiler
|
|||
///< Generate code for parsed expression.
|
||||
/// \return Type ('l': integer, 'f': float)
|
||||
|
||||
void parseArguments (const std::string& arguments, Scanner& scanner,
|
||||
int parseArguments (const std::string& arguments, Scanner& scanner,
|
||||
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, 'c': string (case smashed))
|
||||
/// 'f': float, 'S': string, 'c': string (case smashed), '/': following arguments are
|
||||
/// optional)
|
||||
/// \param invert Store arguments in reverted order.
|
||||
/// \return number of optional arguments
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -53,48 +53,77 @@ namespace Compiler
|
|||
}
|
||||
|
||||
void Extensions::registerFunction (const std::string& keyword, char returnType,
|
||||
const std::string& argumentType, int segment5code, int segment5codeExplicit)
|
||||
const std::string& argumentType, int code, int codeExplicit)
|
||||
{
|
||||
assert (segment5code>=33554432 && segment5code<=67108863);
|
||||
|
||||
int code = mNextKeywordIndex--;
|
||||
|
||||
mKeywords.insert (std::make_pair (keyword, code));
|
||||
|
||||
Function function;
|
||||
|
||||
if (argumentType.find ('/')==std::string::npos)
|
||||
{
|
||||
function.mSegment = 5;
|
||||
assert (code>=33554432 && code<=67108863);
|
||||
assert (codeExplicit==-1 || (codeExplicit>=33554432 && codeExplicit<=67108863));
|
||||
}
|
||||
else
|
||||
{
|
||||
function.mSegment = 3;
|
||||
assert (code>=0x20000 && code<=0x2ffff);
|
||||
assert (codeExplicit==-1 || (codeExplicit>=0x20000 && codeExplicit<=0x2ffff));
|
||||
}
|
||||
|
||||
int keywordIndex = mNextKeywordIndex--;
|
||||
|
||||
mKeywords.insert (std::make_pair (keyword, keywordIndex));
|
||||
|
||||
function.mReturn = returnType;
|
||||
function.mArguments = argumentType;
|
||||
function.mCode = segment5code;
|
||||
function.mCodeExplicit = segment5codeExplicit;
|
||||
function.mCode = code;
|
||||
function.mCodeExplicit = codeExplicit;
|
||||
|
||||
mFunctions.insert (std::make_pair (code, function));
|
||||
mFunctions.insert (std::make_pair (keywordIndex, function));
|
||||
}
|
||||
|
||||
void Extensions::registerInstruction (const std::string& keyword,
|
||||
const std::string& argumentType, int segment5code, int segment5codeExplicit)
|
||||
const std::string& argumentType, int code, int codeExplicit)
|
||||
{
|
||||
assert (segment5code>=33554432 && segment5code<=67108863);
|
||||
|
||||
int code = mNextKeywordIndex--;
|
||||
|
||||
mKeywords.insert (std::make_pair (keyword, code));
|
||||
|
||||
Instruction instruction;
|
||||
instruction.mArguments = argumentType;
|
||||
instruction.mCode = segment5code;
|
||||
instruction.mCodeExplicit = segment5codeExplicit;
|
||||
|
||||
mInstructions.insert (std::make_pair (code, instruction));
|
||||
if (argumentType.find ('/')==std::string::npos)
|
||||
{
|
||||
instruction.mSegment = 5;
|
||||
assert (code>=33554432 && code<=67108863);
|
||||
assert (codeExplicit==-1 || (codeExplicit>=33554432 && codeExplicit<=67108863));
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction.mSegment = 3;
|
||||
assert (code>=0x20000 && code<=0x2ffff);
|
||||
assert (codeExplicit==-1 || (codeExplicit>=0x20000 && codeExplicit<=0x2ffff));
|
||||
}
|
||||
|
||||
int keywordIndex = mNextKeywordIndex--;
|
||||
|
||||
mKeywords.insert (std::make_pair (keyword, keywordIndex));
|
||||
|
||||
instruction.mArguments = argumentType;
|
||||
instruction.mCode = code;
|
||||
instruction.mCodeExplicit = codeExplicit;
|
||||
|
||||
mInstructions.insert (std::make_pair (keywordIndex, instruction));
|
||||
}
|
||||
|
||||
void Extensions::generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
|
||||
Literals& literals, const std::string& id) const
|
||||
Literals& literals, const std::string& id, int optionalArguments) const
|
||||
{
|
||||
assert (optionalArguments>=0);
|
||||
|
||||
std::map<int, Function>::const_iterator iter = mFunctions.find (keyword);
|
||||
|
||||
if (iter==mFunctions.end())
|
||||
throw std::logic_error ("unknown custom function keyword");
|
||||
|
||||
if (optionalArguments && iter->second.mSegment!=3)
|
||||
throw std::logic_error ("functions with optional arguments must be placed into segment 3");
|
||||
|
||||
if (!id.empty())
|
||||
{
|
||||
if (iter->second.mCodeExplicit==-1)
|
||||
|
@ -104,19 +133,46 @@ namespace Compiler
|
|||
Generator::pushInt (code, literals, index);
|
||||
}
|
||||
|
||||
code.push_back (Generator::segment5 (
|
||||
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit));
|
||||
switch (iter->second.mSegment)
|
||||
{
|
||||
case 3:
|
||||
|
||||
if (optionalArguments>=256)
|
||||
throw std::logic_error ("number of optional arguments is too large for segment 3");
|
||||
|
||||
code.push_back (Generator::segment3 (
|
||||
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit,
|
||||
optionalArguments));
|
||||
|
||||
break;
|
||||
|
||||
case 5:
|
||||
|
||||
code.push_back (Generator::segment5 (
|
||||
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
throw std::logic_error ("unsupported code segment");
|
||||
}
|
||||
}
|
||||
|
||||
void Extensions::generateInstructionCode (int keyword,
|
||||
std::vector<Interpreter::Type_Code>& code, Literals& literals, const std::string& id)
|
||||
const
|
||||
std::vector<Interpreter::Type_Code>& code, Literals& literals, const std::string& id,
|
||||
int optionalArguments) const
|
||||
{
|
||||
assert (optionalArguments>=0);
|
||||
|
||||
std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword);
|
||||
|
||||
if (iter==mInstructions.end())
|
||||
throw std::logic_error ("unknown custom instruction keyword");
|
||||
|
||||
if (optionalArguments && iter->second.mSegment!=3)
|
||||
throw std::logic_error ("instructions with optional arguments must be placed into segment 3");
|
||||
|
||||
if (!id.empty())
|
||||
{
|
||||
if (iter->second.mCodeExplicit==-1)
|
||||
|
@ -126,7 +182,29 @@ namespace Compiler
|
|||
Generator::pushInt (code, literals, index);
|
||||
}
|
||||
|
||||
code.push_back (Generator::segment5 (
|
||||
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit));
|
||||
switch (iter->second.mSegment)
|
||||
{
|
||||
case 3:
|
||||
|
||||
if (optionalArguments>=256)
|
||||
throw std::logic_error ("number of optional arguments is too large for segment 3");
|
||||
|
||||
code.push_back (Generator::segment3 (
|
||||
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit,
|
||||
optionalArguments));
|
||||
|
||||
break;
|
||||
|
||||
case 5:
|
||||
|
||||
code.push_back (Generator::segment5 (
|
||||
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
throw std::logic_error ("unsupported code segment");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace Compiler
|
|||
std::string mArguments;
|
||||
int mCode;
|
||||
int mCodeExplicit;
|
||||
int mSegment;
|
||||
};
|
||||
|
||||
struct Instruction
|
||||
|
@ -28,6 +29,7 @@ namespace Compiler
|
|||
std::string mArguments;
|
||||
int mCode;
|
||||
int mCodeExplicit;
|
||||
int mSegment;
|
||||
};
|
||||
|
||||
int mNextKeywordIndex;
|
||||
|
@ -54,30 +56,29 @@ namespace Compiler
|
|||
///< 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, int segment5codeExplicit = -1);
|
||||
const std::string& argumentType, int code, int codeExplicit = -1);
|
||||
///< Register a custom function
|
||||
/// - keyword must be all lower case.
|
||||
/// - keyword must be unique
|
||||
/// - if explicit references are not supported, segment5codeExplicit must be set to -1
|
||||
/// \note Currently only segment 5 opcodes are supported.
|
||||
/// \note Currently only segment 3 and segment 5 opcodes are supported.
|
||||
|
||||
void registerInstruction (const std::string& keyword,
|
||||
const std::string& argumentType, int segment5code, int segment5codeExplicit = -1);
|
||||
const std::string& argumentType, int code, int codeExplicit = -1);
|
||||
///< Register a custom instruction
|
||||
/// - keyword must be all lower case.
|
||||
/// - keyword must be unique
|
||||
/// - if explicit references are not supported, segment5codeExplicit must be set to -1
|
||||
/// \note Currently only segment 5 opcodes are supported.
|
||||
/// \note Currently only segment 3 and segment 5 opcodes are supported.
|
||||
|
||||
void generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
|
||||
Literals& literals, const std::string& id) const;
|
||||
Literals& literals, const std::string& id, int optionalArguments) const;
|
||||
///< Append code for function to \a code.
|
||||
|
||||
void generateInstructionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
|
||||
Literals& literals, const std::string& id) const;
|
||||
Literals& literals, const std::string& id, int optionalArguments) const;
|
||||
///< Append code for function to \a code.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -113,6 +113,6 @@ namespace Compiler
|
|||
mState = BeginState;
|
||||
mName.clear();
|
||||
mScriptParser.reset();
|
||||
Parser::reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -505,7 +505,10 @@ namespace Compiler
|
|||
void message (CodeContainer& code, Literals& literals, const std::string& message,
|
||||
int buttons)
|
||||
{
|
||||
assert (buttons==0);
|
||||
assert (buttons>=0);
|
||||
|
||||
if (buttons>=256)
|
||||
throw std::runtime_error ("A message box can't have more than 255 buttons");
|
||||
|
||||
int index = literals.addString (message);
|
||||
|
||||
|
@ -773,4 +776,3 @@ namespace Compiler
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ namespace Compiler
|
|||
|
||||
inline Interpreter::Type_Code segment3 (unsigned int c, unsigned int arg0)
|
||||
{
|
||||
assert (c<1024);
|
||||
return 0xc0000000 | (c<<20) | (arg0 & 0xffff);
|
||||
assert (c<262144);
|
||||
return 0xc0000000 | (c<<8) | (arg0 & 0xff);
|
||||
}
|
||||
|
||||
inline Interpreter::Type_Code segment4 (unsigned int c, unsigned int arg0,
|
||||
|
@ -120,4 +120,3 @@ namespace Compiler
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -168,13 +168,26 @@ namespace Compiler
|
|||
mExprParser.parseArguments (arguments, scanner, mCode, true);
|
||||
}
|
||||
|
||||
// for now skip buttons
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
mName = name;
|
||||
mButtons = 0;
|
||||
|
||||
Generator::message (mCode, mLiterals, name, 0);
|
||||
mState = EndState;
|
||||
return false;
|
||||
mState = MessageButtonState;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mState==MessageButtonState || mState==MessageButtonCommaState)
|
||||
{
|
||||
Generator::pushString (mCode, mLiterals, name);
|
||||
mState = MessageButtonState;
|
||||
++mButtons;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mState==BeginState && getContext().isId (name))
|
||||
{
|
||||
mState = PotentialExplicitState;
|
||||
mExplicit = toLower (name);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mState==BeginState && mAllowExpression)
|
||||
|
@ -200,13 +213,6 @@ namespace Compiler
|
|||
}
|
||||
}
|
||||
|
||||
if (mState==BeginState && getContext().isId (name))
|
||||
{
|
||||
mState = PotentialExplicitState;
|
||||
mExplicit = toLower (name);
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parser::parseName (name, loc, scanner);
|
||||
}
|
||||
|
||||
|
@ -236,9 +242,9 @@ namespace Compiler
|
|||
|
||||
if (extensions->isInstruction (keyword, argumentType, mState==ExplicitState))
|
||||
{
|
||||
mExprParser.parseArguments (argumentType, scanner, mCode, true);
|
||||
int optionals = mExprParser.parseArguments (argumentType, scanner, mCode, true);
|
||||
|
||||
extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit);
|
||||
extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit, optionals);
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
|
@ -360,6 +366,18 @@ namespace Compiler
|
|||
return true;
|
||||
}
|
||||
|
||||
if (code==Scanner::S_newline && mState==MessageButtonState)
|
||||
{
|
||||
Generator::message (mCode, mLiterals, mName, mButtons);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (code==Scanner::S_comma && mState==MessageButtonState)
|
||||
{
|
||||
mState = MessageButtonCommaState;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mAllowExpression && mState==BeginState &&
|
||||
(code==Scanner::S_open || code==Scanner::S_minus))
|
||||
{
|
||||
|
@ -378,4 +396,3 @@ namespace Compiler
|
|||
mExplicit.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Compiler
|
|||
BeginState,
|
||||
ShortState, LongState, FloatState,
|
||||
SetState, SetLocalVarState, SetGlobalVarState,
|
||||
MessageState, MessageCommaState,
|
||||
MessageState, MessageCommaState, MessageButtonState, MessageButtonCommaState,
|
||||
EndState,
|
||||
PotentialExplicitState, ExplicitState
|
||||
};
|
||||
|
@ -32,6 +32,7 @@ namespace Compiler
|
|||
std::vector<Interpreter::Type_Code>& mCode;
|
||||
State mState;
|
||||
std::string mName;
|
||||
int mButtons;
|
||||
std::string mExplicit;
|
||||
char mType;
|
||||
ExprParser mExprParser;
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace Compiler
|
|||
}
|
||||
|
||||
Parser::Parser (ErrorHandler& errorHandler, Context& context)
|
||||
: mErrorHandler (errorHandler), mContext (context)
|
||||
: mErrorHandler (errorHandler), mContext (context), mOptional (false), mEmpty (true)
|
||||
{}
|
||||
|
||||
// destructor
|
||||
|
@ -79,7 +79,9 @@ namespace Compiler
|
|||
|
||||
bool Parser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
reportSeriousError ("Unexpected numeric value", loc);
|
||||
if (!(mOptional && mEmpty))
|
||||
reportSeriousError ("Unexpected numeric value", loc);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -90,7 +92,9 @@ namespace Compiler
|
|||
|
||||
bool Parser::parseFloat (float value, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
reportSeriousError ("Unexpected floating point value", loc);
|
||||
if (!(mOptional && mEmpty))
|
||||
reportSeriousError ("Unexpected floating point value", loc);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -102,7 +106,9 @@ namespace Compiler
|
|||
bool Parser::parseName (const std::string& name, const TokenLoc& loc,
|
||||
Scanner& scanner)
|
||||
{
|
||||
reportSeriousError ("Unexpected name", loc);
|
||||
if (!(mOptional && mEmpty))
|
||||
reportSeriousError ("Unexpected name", loc);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -113,7 +119,9 @@ namespace Compiler
|
|||
|
||||
bool Parser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
reportSeriousError ("Unexpected keyword", loc);
|
||||
if (!(mOptional && mEmpty))
|
||||
reportSeriousError ("Unexpected keyword", loc);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -124,7 +132,9 @@ namespace Compiler
|
|||
|
||||
bool Parser::parseSpecial (int code, const TokenLoc& loc, Scanner& scanner)
|
||||
{
|
||||
reportSeriousError ("Unexpected special token", loc);
|
||||
if (!(mOptional && mEmpty))
|
||||
reportSeriousError ("Unexpected special token", loc);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -136,5 +146,25 @@ namespace Compiler
|
|||
{
|
||||
reportEOF();
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::reset()
|
||||
{
|
||||
mOptional = false;
|
||||
mEmpty = true;
|
||||
}
|
||||
|
||||
void Parser::setOptional (bool optional)
|
||||
{
|
||||
mOptional = optional;
|
||||
}
|
||||
|
||||
void Parser::start()
|
||||
{
|
||||
mEmpty = false;
|
||||
}
|
||||
|
||||
bool Parser::isEmpty() const
|
||||
{
|
||||
return mEmpty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ namespace Compiler
|
|||
{
|
||||
ErrorHandler& mErrorHandler;
|
||||
Context& mContext;
|
||||
bool mOptional;
|
||||
bool mEmpty;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -47,7 +49,7 @@ namespace Compiler
|
|||
///< constructor
|
||||
|
||||
virtual ~Parser();
|
||||
///< destructor
|
||||
///< destructor
|
||||
|
||||
virtual bool parseInt (int value, const TokenLoc& loc, Scanner& scanner);
|
||||
///< Handle an int token.
|
||||
|
@ -84,6 +86,19 @@ namespace Compiler
|
|||
///< Handle EOF token.
|
||||
///
|
||||
/// - Default-implementation: Report an error.
|
||||
|
||||
virtual void reset();
|
||||
///< Reset parser to clean state.
|
||||
|
||||
void setOptional (bool optional);
|
||||
///< Optional mode: If nothign has been parsed yet and an unexpected token is delivered, stop
|
||||
/// parsing without raising an exception (after a reset the parser is in non-optional mode).
|
||||
|
||||
void start();
|
||||
///< Mark parser as non-empty (at least one token has been parser).
|
||||
|
||||
bool isEmpty() const;
|
||||
///< Has anything been parsed?
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace Compiler
|
|||
{
|
||||
if (mState==StartState || mState==CommaState)
|
||||
{
|
||||
start();
|
||||
if (mSmashCase)
|
||||
Generator::pushString (mCode, mLiterals, toLower (name));
|
||||
else
|
||||
|
@ -52,6 +53,7 @@ namespace Compiler
|
|||
mState = StartState;
|
||||
mCode.clear();
|
||||
mSmashCase = false;
|
||||
Parser::reset();
|
||||
}
|
||||
|
||||
void StringParser::smashCase()
|
||||
|
@ -59,4 +61,3 @@ namespace Compiler
|
|||
mSmashCase = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,28 +3,18 @@
|
|||
|
||||
#include <string>
|
||||
#include <libs/platform/stdint.h>
|
||||
#include <libs/platform/string.h>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <libs/mangle/stream/stream.hpp>
|
||||
#include <libs/mangle/stream/servers/file_stream.hpp>
|
||||
#include <libs/mangle/tools/str_exception.hpp>
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#ifdef __APPLE__
|
||||
// need our own implementation of strnlen
|
||||
static size_t strnlen(const char *s, size_t n)
|
||||
{
|
||||
const char *p = (const char *)memchr(s, 0, n);
|
||||
return(p ? p-s : n);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace ESM {
|
||||
|
||||
enum Version
|
||||
|
@ -626,7 +616,7 @@ public:
|
|||
ss << "\n Subrecord: " << c.subName.toString();
|
||||
if(esm != NULL)
|
||||
ss << "\n Offset: 0x" << hex << esm->tell();
|
||||
throw str_exception(ss.str());
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -45,4 +45,113 @@ namespace ESM
|
|||
|
||||
esm.skipRecord();
|
||||
}
|
||||
|
||||
void DialInfo::load(ESMReader &esm)
|
||||
{
|
||||
id = esm.getHNString("INAM");
|
||||
prev = esm.getHNString("PNAM");
|
||||
next = esm.getHNString("NNAM");
|
||||
|
||||
// Not present if deleted
|
||||
if(esm.isNextSub("DATA"))
|
||||
esm.getHT(data, 12);
|
||||
|
||||
// What follows is somewhat spaghetti-ish, but it's worth if for
|
||||
// an extra speedup. INFO is by far the most common record type.
|
||||
|
||||
// subName is a reference to the original, so it changes whenever
|
||||
// a new sub name is read. esm.isEmptyOrGetName() will get the
|
||||
// next name for us, or return true if there are no more records.
|
||||
esm.getSubName();
|
||||
const NAME &subName = esm.retSubName();
|
||||
|
||||
if(subName.val == REC_ONAM)
|
||||
{
|
||||
actor = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_RNAM)
|
||||
{
|
||||
race = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_CNAM)
|
||||
{
|
||||
clas = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
|
||||
factionLess = false;
|
||||
if(subName.val == REC_FNAM)
|
||||
{
|
||||
npcFaction = esm.getHString();
|
||||
if(npcFaction == "FFFF") factionLess = true;
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_ANAM)
|
||||
{
|
||||
cell = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_DNAM)
|
||||
{
|
||||
pcFaction = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_SNAM)
|
||||
{
|
||||
sound = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_NAME)
|
||||
{
|
||||
response = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
|
||||
while(subName.val == REC_SCVR)
|
||||
{
|
||||
SelectStruct ss;
|
||||
|
||||
ss.selectRule = esm.getHString();
|
||||
esm.isEmptyOrGetName();
|
||||
|
||||
if(subName.val == REC_INTV)
|
||||
{
|
||||
ss.type = VT_Int;
|
||||
esm.getHT(ss.i);
|
||||
}
|
||||
else if(subName.val == REC_FLTV)
|
||||
{
|
||||
ss.type = VT_Float;
|
||||
esm.getHT(ss.f);
|
||||
}
|
||||
else
|
||||
esm.fail("INFO.SCVR must precede INTV or FLTV, not "
|
||||
+ subName.toString());
|
||||
|
||||
selects.push_back(ss);
|
||||
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
|
||||
if(subName.val == REC_BNAM)
|
||||
{
|
||||
resultScript = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
|
||||
questStatus = QS_None;
|
||||
|
||||
if (subName.val == REC_QSTN) questStatus = QS_Name;
|
||||
else if(subName.val == REC_QSTF) questStatus = QS_Finished;
|
||||
else if(subName.val == REC_QSTR) questStatus = QS_Restart;
|
||||
else if(subName.val == REC_DELE) questStatus = QS_Deleted;
|
||||
else
|
||||
esm.fail("Don't know what to do with " + subName.toString() + " in INFO " + id);
|
||||
|
||||
if(questStatus != QS_None)
|
||||
// Skip rest of record
|
||||
esm.skipRecord();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,114 +96,7 @@ struct DialInfo
|
|||
REC_DELE = 0x454c4544
|
||||
};
|
||||
|
||||
void load(ESMReader &esm)
|
||||
{
|
||||
id = esm.getHNString("INAM");
|
||||
prev = esm.getHNString("PNAM");
|
||||
next = esm.getHNString("NNAM");
|
||||
|
||||
// Not present if deleted
|
||||
if(esm.isNextSub("DATA"))
|
||||
esm.getHT(data, 12);
|
||||
|
||||
// What follows is somewhat spaghetti-ish, but it's worth if for
|
||||
// an extra speedup. INFO is by far the most common record type.
|
||||
|
||||
// subName is a reference to the original, so it changes whenever
|
||||
// a new sub name is read. esm.isEmptyOrGetName() will get the
|
||||
// next name for us, or return true if there are no more records.
|
||||
esm.getSubName();
|
||||
const NAME &subName = esm.retSubName();
|
||||
|
||||
if(subName.val == REC_ONAM)
|
||||
{
|
||||
actor = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_RNAM)
|
||||
{
|
||||
race = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_CNAM)
|
||||
{
|
||||
clas = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
|
||||
factionLess = false;
|
||||
if(subName.val == REC_FNAM)
|
||||
{
|
||||
npcFaction = esm.getHString();
|
||||
if(npcFaction == "FFFF") factionLess = true;
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_ANAM)
|
||||
{
|
||||
cell = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_DNAM)
|
||||
{
|
||||
pcFaction = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_SNAM)
|
||||
{
|
||||
sound = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
if(subName.val == REC_NAME)
|
||||
{
|
||||
response = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
|
||||
while(subName.val == REC_SCVR)
|
||||
{
|
||||
SelectStruct ss;
|
||||
|
||||
ss.selectRule = esm.getHString();
|
||||
esm.isEmptyOrGetName();
|
||||
|
||||
if(subName.val == REC_INTV)
|
||||
{
|
||||
ss.type = VT_Int;
|
||||
esm.getHT(ss.i);
|
||||
}
|
||||
else if(subName.val == REC_FLTV)
|
||||
{
|
||||
ss.type = VT_Float;
|
||||
esm.getHT(ss.f);
|
||||
}
|
||||
else
|
||||
esm.fail("INFO.SCVR must precede INTV or FLTV, not "
|
||||
+ subName.toString());
|
||||
|
||||
selects.push_back(ss);
|
||||
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
|
||||
if(subName.val == REC_BNAM)
|
||||
{
|
||||
resultScript = esm.getHString();
|
||||
if(esm.isEmptyOrGetName()) return;
|
||||
}
|
||||
|
||||
questStatus = QS_None;
|
||||
int skip = 1;
|
||||
|
||||
if (subName.val == REC_QSTN) questStatus = QS_Name;
|
||||
else if(subName.val == REC_QSTF) questStatus = QS_Finished;
|
||||
else if(subName.val == REC_QSTR) questStatus = QS_Restart;
|
||||
else if(subName.val == REC_DELE) {questStatus = QS_Deleted; skip = 4;}
|
||||
else
|
||||
esm.fail("Don't know what to do with " + subName.toString() + " in INFO " + id);
|
||||
|
||||
if(questStatus != QS_None)
|
||||
esm.skip(skip);
|
||||
}
|
||||
void load(ESMReader &esm);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -13,11 +13,10 @@
|
|||
#include "store.hpp"
|
||||
#include "components/esm/records.hpp"
|
||||
#include "components/esm/loadcell.hpp"
|
||||
#include <libs/mangle/tools/str_exception.hpp>
|
||||
#include <list>
|
||||
|
||||
#include <iostream>
|
||||
#include "libs/mangle/tools/str_exception.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace ESMS
|
||||
{
|
||||
|
@ -55,7 +54,7 @@ namespace ESMS
|
|||
{
|
||||
const X* obj = recList.find(ref.refID);
|
||||
if(obj == NULL)
|
||||
throw str_exception("Error resolving cell reference " + ref.refID);
|
||||
throw std::runtime_error("Error resolving cell reference " + ref.refID);
|
||||
|
||||
LiveRef lr;
|
||||
lr.ref = ref;
|
||||
|
@ -116,7 +115,7 @@ namespace ESMS
|
|||
cell = store.cells.findInt(name);
|
||||
|
||||
if(cell == NULL)
|
||||
throw str_exception("Cell not found - " + name);
|
||||
throw std::runtime_error("Cell not found - " + name);
|
||||
|
||||
loadRefs(store, esm);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ Code bit-patterns:
|
|||
00ccccccAAAAAAAAAAAAAAAAAAAAAAAA segment 0: 64 opcodes, 1 24-bit argument
|
||||
01ccccccAAAAAAAAAAAABBBBBBBBBBBB segment 1: 64 opcodes, 2 12-bit arguments
|
||||
10ccccccccccAAAAAAAAAAAAAAAAAAAA segment 2: 1024 opcodes, 1 20-bit argument
|
||||
110000ccccccccccAAAAAAAAAAAAAAAA segment 3: 1024 opcodes, 1 16-bit argument
|
||||
110000ccccccccccccccccccAAAAAAAA segment 3: 262144 opcodes, 1 8-bit argument
|
||||
110001ccccccccccAAAAAAAABBBBBBBB segment 4: 1024 opcodes, 2 8-bit arguments
|
||||
110010cccccccccccccccccccccccccc segment 5: 67108864 opcodes, no arguments
|
||||
other bit-patterns reserved
|
||||
|
@ -31,8 +31,8 @@ B: argument 1
|
|||
|
||||
Segment 0:
|
||||
op 0: push arg0
|
||||
op 1: move pv ahead by arg0
|
||||
op 2: move pv back by arg0
|
||||
op 1: move pc ahead by arg0
|
||||
op 2: move pc back by arg0
|
||||
opcodes 3-31 unused
|
||||
opcodes 32-63 reserved for extensions
|
||||
|
||||
|
@ -50,8 +50,8 @@ op 0: show message box with message string literal index in stack[0];
|
|||
additional arguments (if any) in stack[arg0+n]..stack[arg0+1];
|
||||
n is determined according to the message string
|
||||
all arguments are removed from stack
|
||||
opcodes 1-511 unused
|
||||
opcodes 512-1023 reserved for extensions
|
||||
opcodes 1-131071 unused
|
||||
opcodes 131072-262143 reserved for extensions
|
||||
|
||||
Segment 4:
|
||||
opcodes 0-511 unused
|
||||
|
@ -119,4 +119,3 @@ op 57: explicit reference = stack[0]; pop;
|
|||
replace stack[0] with distance between explicit reference and a reference of ID stack[0]
|
||||
opcodes 58-33554431 unused
|
||||
opcodes 33554432-67108863 reserved for extensions
|
||||
|
||||
|
|
|
@ -69,8 +69,8 @@ namespace Interpreter
|
|||
{
|
||||
case 0x30:
|
||||
{
|
||||
int opcode = (code>>16) & 0x3ff;
|
||||
unsigned int arg0 = code & 0xffff;
|
||||
int opcode = (code>>8) & 0x3ffff;
|
||||
unsigned int arg0 = code & 0xff;
|
||||
|
||||
std::map<int, Opcode1 *>::iterator iter = mSegment3.find (opcode);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "opcodes.hpp"
|
||||
#include "runtime.hpp"
|
||||
|
@ -18,14 +19,23 @@ namespace Interpreter
|
|||
|
||||
virtual void execute (Runtime& runtime, unsigned int arg0)
|
||||
{
|
||||
if (arg0!=0)
|
||||
throw std::logic_error ("message box buttons not implemented yet");
|
||||
|
||||
// message
|
||||
int index = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
std::string message = runtime.getStringLiteral (index);
|
||||
|
||||
// buttons
|
||||
std::vector<std::string> buttons;
|
||||
|
||||
for (std::size_t i=0; i<arg0; ++i)
|
||||
{
|
||||
int index = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
buttons.push_back (runtime.getStringLiteral (index));
|
||||
}
|
||||
|
||||
std::reverse (buttons.begin(), buttons.end());
|
||||
|
||||
// additional parameters
|
||||
std::string formattedMessage;
|
||||
|
||||
|
@ -82,9 +92,6 @@ namespace Interpreter
|
|||
}
|
||||
}
|
||||
|
||||
// buttons (not implemented)
|
||||
std::vector<std::string> buttons;
|
||||
|
||||
runtime.getContext().messageBox (formattedMessage, buttons);
|
||||
}
|
||||
};
|
||||
|
@ -206,4 +213,3 @@ namespace Interpreter
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
// A simple array implementation containing a pointer and a
|
||||
// length. Used for holding slices into a data buffer.
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
template <class T>
|
||||
struct SliceArray
|
||||
{
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
|
||||
#include <libs/mangle/stream/stream.hpp>
|
||||
#include <libs/mangle/stream/filters/buffer_stream.hpp>
|
||||
#include <libs/mangle/tools/str_exception.hpp>
|
||||
#include <components/misc/slice_array.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
|
@ -69,7 +69,7 @@ class NIFFile
|
|||
{
|
||||
std::string err = "NIFFile Error: " + msg;
|
||||
err += "\nFile: " + filename;
|
||||
throw str_exception(err);
|
||||
throw std::runtime_error(err);
|
||||
}
|
||||
|
||||
/// Open a NIF stream. The name is used for error messages.
|
||||
|
|
|
@ -767,14 +767,20 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
|
|||
|
||||
if (!skel.isNull()) //if there is a skeleton
|
||||
{
|
||||
bone = skel->createBone(node->name.toString());
|
||||
std::string name = node->name.toString();
|
||||
// Quick-n-dirty workaround for the fact that several
|
||||
// bones may have the same name.
|
||||
if(!skel->hasBone(name))
|
||||
{
|
||||
bone = skel->createBone(name);
|
||||
|
||||
if (parentBone)
|
||||
parentBone->addChild(bone);
|
||||
if (parentBone)
|
||||
parentBone->addChild(bone);
|
||||
|
||||
bone->setInheritOrientation(true);
|
||||
bone->setPosition(convertVector3(node->trafo->pos));
|
||||
bone->setOrientation(convertRotation(node->trafo->rotation));
|
||||
bone->setInheritOrientation(true);
|
||||
bone->setPosition(convertVector3(node->trafo->pos));
|
||||
bone->setOrientation(convertRotation(node->trafo->rotation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,6 @@ include_directories(
|
|||
${OGRE_INCLUDE_DIR}
|
||||
)
|
||||
include(MyGUI.OgrePlatform.list)
|
||||
add_library(MyGUI.OgrePlatform ${HEADER_FILES} ${SOURCE_FILES})
|
||||
target_link_libraries(MyGUI.OgrePlatform ${OGRE_LIBRARIES})
|
||||
add_library(MyGUIOgrePlatform ${HEADER_FILES} ${SOURCE_FILES})
|
||||
target_link_libraries(MyGUIOgrePlatform ${OGRE_LIBRARIES})
|
||||
link_directories(${OGRE_LIB_DIR})
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 3324f6494c021e3dc69cd76ace5ff25a52e4bcce
|
||||
Subproject commit b08c2f78dc24f05f67a998114880200518602690
|
|
@ -1 +1 @@
|
|||
Subproject commit 2e2f8e9725fd1a27a82d0ad5c6c0e296e715eb60
|
||||
Subproject commit 377e7d71ceea5a1ca166b8df9a03a5b68df83bc5
|
|
@ -2,6 +2,12 @@
|
|||
#ifndef _STDINT_WRAPPER_H
|
||||
#define _STDINT_WRAPPER_H
|
||||
|
||||
#if (_MSC_VER >= 1600)
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
// Pull the boost names into the global namespace for convenience
|
||||
|
@ -11,3 +17,5 @@ using boost::int64_t;
|
|||
using boost::uint64_t;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
14
libs/platform/string.h
Normal file
14
libs/platform/string.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Wrapper for string.h on Mac
|
||||
#ifndef _STRING_WRAPPER_H
|
||||
#define _STRING_WRAPPER_H
|
||||
|
||||
#include <string.h>
|
||||
#ifdef __APPLE__
|
||||
// need our own implementation of strnlen
|
||||
static size_t strnlen(const char *s, size_t n)
|
||||
{
|
||||
const char *p = (const char *)memchr(s, 0, n);
|
||||
return(p ? p-s : n);
|
||||
}
|
||||
#endif
|
||||
#endif
|
Loading…
Reference in a new issue