mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-19 19:11:32 +00:00
Preparation for console
git-svn-id: https://openmw.svn.sourceforge.net/svnroot/openmw/trunk@103 ea6a568a-9f4f-0410-981a-c910a81bb256
This commit is contained in:
parent
714b724bf2
commit
1b01de4294
25 changed files with 470 additions and 127 deletions
2
Makefile
2
Makefile
|
@ -38,7 +38,7 @@ bullet_cpp_files=$(bullet_cpp:%=bullet/cpp_%.cpp)
|
||||||
# All object files needed by openmw and esmtool
|
# All object files needed by openmw and esmtool
|
||||||
src := $(wildcard bsa/*.d) $(wildcard bullet/*.d) $(wildcard core/*.d) \
|
src := $(wildcard bsa/*.d) $(wildcard bullet/*.d) $(wildcard core/*.d) \
|
||||||
$(wildcard esm/*.d) $(wildcard input/*.d) $(wildcard nif/*.d) $(wildcard ogre/*.d) \
|
$(wildcard esm/*.d) $(wildcard input/*.d) $(wildcard nif/*.d) $(wildcard ogre/*.d) \
|
||||||
$(wildcard scene/*.d) $(wildcard sound/*.d) $(wildcard util/*.d)
|
$(wildcard scene/*.d) $(wildcard sound/*.d) $(wildcard util/*.d) $(wildcard gui/*.d)
|
||||||
src := $(src) $(wildcard mscripts/*.d)
|
src := $(src) $(wildcard mscripts/*.d)
|
||||||
src := $(src) monster/monster.d \
|
src := $(src) monster/monster.d \
|
||||||
$(wildcard monster/vm/*.d) \
|
$(wildcard monster/vm/*.d) \
|
||||||
|
|
|
@ -35,8 +35,11 @@ extern(C):
|
||||||
// Initialize the dynamic world. Returns non-zero if an error occurs.
|
// Initialize the dynamic world. Returns non-zero if an error occurs.
|
||||||
int bullet_init();
|
int bullet_init();
|
||||||
|
|
||||||
// Switch to the next physics mode
|
// Set physics modes
|
||||||
void bullet_nextMode();
|
void bullet_nextMode();
|
||||||
|
void bullet_walk();
|
||||||
|
void bullet_fly();
|
||||||
|
void bullet_ghost();
|
||||||
|
|
||||||
// Warp the player to a specific location.
|
// Warp the player to a specific location.
|
||||||
void bullet_movePlayer(float x, float y, float z);
|
void bullet_movePlayer(float x, float y, float z);
|
||||||
|
|
|
@ -206,29 +206,45 @@ extern "C" int32_t bullet_init()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set physics modes
|
||||||
|
extern "C" void bullet_walk()
|
||||||
|
{
|
||||||
|
g_physMode = PHYS_WALK;
|
||||||
|
cout << "Walk mode\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void bullet_fly()
|
||||||
|
{
|
||||||
|
g_physMode = PHYS_FLY;
|
||||||
|
cout << "Fly mode\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void bullet_ghost()
|
||||||
|
{
|
||||||
|
g_physMode = PHYS_GHOST;
|
||||||
|
cout << "Ghost mode\n";
|
||||||
|
}
|
||||||
|
|
||||||
// Switch to the next physics mode
|
// Switch to the next physics mode
|
||||||
extern "C" void bullet_nextMode()
|
extern "C" void bullet_nextMode()
|
||||||
{
|
{
|
||||||
g_physMode++;
|
|
||||||
if(g_physMode > PHYS_GHOST)
|
|
||||||
g_physMode = PHYS_WALK;
|
|
||||||
|
|
||||||
switch(g_physMode)
|
switch(g_physMode)
|
||||||
{
|
{
|
||||||
case PHYS_WALK:
|
case PHYS_WALK:
|
||||||
cout << "Entering walking mode\n";
|
bullet_fly();
|
||||||
break;
|
break;
|
||||||
case PHYS_FLY:
|
case PHYS_FLY:
|
||||||
cout << "Entering flying mode\n";
|
bullet_ghost();
|
||||||
break;
|
break;
|
||||||
case PHYS_GHOST:
|
case PHYS_GHOST:
|
||||||
cout << "Entering ghost mode\n";
|
bullet_walk();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warp the player to a specific location. We do not bother setting
|
// Warp the player to a specific location. We do not bother setting
|
||||||
// rotation, since it's completely irrelevant for collision detection.
|
// rotation, since it's completely irrelevant for collision detection,
|
||||||
|
// and doubly so since the collision mesh is a sphere.
|
||||||
extern "C" void bullet_movePlayer(float x, float y, float z)
|
extern "C" void bullet_movePlayer(float x, float y, float z)
|
||||||
{
|
{
|
||||||
btTransform tr;
|
btTransform tr;
|
||||||
|
|
|
@ -164,7 +164,7 @@ struct NPC
|
||||||
|
|
||||||
skipRecord();
|
skipRecord();
|
||||||
|
|
||||||
makeProto("Person");
|
makeProto();
|
||||||
|
|
||||||
// Clean this up a little later, eg. no point in storing the
|
// Clean this up a little later, eg. no point in storing the
|
||||||
// structs outside the function any longer. Same goes for most of
|
// structs outside the function any longer. Same goes for most of
|
||||||
|
|
53
gui/bindings.d
Normal file
53
gui/bindings.d
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
OpenMW - The completely unofficial reimplementation of Morrowind
|
||||||
|
Copyright (C) 2008 Nicolay Korslund
|
||||||
|
Email: < korslund@gmail.com >
|
||||||
|
WWW: http://openmw.snaptoad.com/
|
||||||
|
|
||||||
|
This file (bindings.d) is part of the OpenMW package.
|
||||||
|
|
||||||
|
OpenMW is distributed as free software: you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License
|
||||||
|
version 3, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
version 3 along with this program. If not, see
|
||||||
|
http://www.gnu.org/licenses/ .
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
module gui.bindings;
|
||||||
|
|
||||||
|
extern(C):
|
||||||
|
|
||||||
|
// GUI functions. Under development. The corresponding C++ functions
|
||||||
|
// are in ogre/cpp_mygui.cpp
|
||||||
|
|
||||||
|
typedef void* WidgetPtr;
|
||||||
|
void gui_setupGUI(int debugOut);
|
||||||
|
void gui_toggleGui();
|
||||||
|
void gui_setCellName(char *str);
|
||||||
|
|
||||||
|
// Get the widget type, as a string
|
||||||
|
char *gui_widgetType(WidgetPtr);
|
||||||
|
|
||||||
|
// Get the height or width of a widget. If the argument is null,
|
||||||
|
// return the size of the screen.
|
||||||
|
int gui_getHeight(WidgetPtr);
|
||||||
|
int gui_getWidth(WidgetPtr);
|
||||||
|
|
||||||
|
// Set various properties of a given widget
|
||||||
|
void gui_setCaption(WidgetPtr, char*);
|
||||||
|
void gui_setNeedMouseFocus(WidgetPtr, int);
|
||||||
|
void gui_setTextColor(WidgetPtr, float,float,float);
|
||||||
|
void gui_setCoord(WidgetPtr, int,int,int,int);
|
||||||
|
|
||||||
|
// Various ways to get or create widgets
|
||||||
|
WidgetPtr gui_loadLayout(char *file, char *prefix, WidgetPtr parent);
|
||||||
|
WidgetPtr gui_getChild(WidgetPtr, char*);
|
||||||
|
WidgetPtr gui_createText(char *skin, int x, int y, int w, int h, char *layer);
|
|
@ -21,11 +21,11 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module ogre.gui;
|
module gui.gui;
|
||||||
|
|
||||||
import monster.monster;
|
import monster.monster;
|
||||||
import monster.vm.mclass;
|
import monster.vm.mclass;
|
||||||
import ogre.bindings;
|
import gui.bindings;
|
||||||
import std.string;
|
import std.string;
|
||||||
|
|
||||||
// Widget class and gui module
|
// Widget class and gui module
|
||||||
|
@ -57,7 +57,7 @@ class MWidget
|
||||||
isLayout = true;
|
isLayout = true;
|
||||||
prefix = format("%s", cast(void*)this);
|
prefix = format("%s", cast(void*)this);
|
||||||
|
|
||||||
widget = gui_loadLayout(layout.ptr, prefix.ptr, parent);
|
widget = gui_loadLayout(layout.toStringz(), prefix.toStringz(), parent);
|
||||||
if(widget is null)
|
if(widget is null)
|
||||||
fail("Layout " ~ layout ~ " is empty");
|
fail("Layout " ~ layout ~ " is empty");
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ class MWidget
|
||||||
name = prefix ~ name;
|
name = prefix ~ name;
|
||||||
|
|
||||||
// Get the child widget
|
// Get the child widget
|
||||||
auto pt = gui_getChild(widget, name.ptr);
|
auto pt = gui_getChild(widget, name.toStringz());
|
||||||
|
|
||||||
if(pt is null)
|
if(pt is null)
|
||||||
fail("Widget has no child named " ~ name);
|
fail("Widget has no child named " ~ name);
|
||||||
|
@ -163,7 +163,7 @@ void setCaption()
|
||||||
foreach(AIndex ind; args)
|
foreach(AIndex ind; args)
|
||||||
res ~= format("%s", arrays.getRef(ind).carr);
|
res ~= format("%s", arrays.getRef(ind).carr);
|
||||||
|
|
||||||
gui_setCaption(getOwner(), res.ptr);
|
gui_setCaption(getOwner(), toStringz(res));
|
||||||
}
|
}
|
||||||
void setNeedMouseFocus()
|
void setNeedMouseFocus()
|
||||||
{ gui_setNeedMouseFocus(getOwner(), stack.popBool); }
|
{ gui_setNeedMouseFocus(getOwner(), stack.popBool); }
|
||||||
|
@ -211,9 +211,9 @@ void text()
|
||||||
int y = stack.popInt();
|
int y = stack.popInt();
|
||||||
int x = stack.popInt();
|
int x = stack.popInt();
|
||||||
char[] skin = stack.popString8();
|
char[] skin = stack.popString8();
|
||||||
WidgetPtr ptr = gui_createText(skin.ptr,
|
WidgetPtr ptr = gui_createText(skin.toStringz(),
|
||||||
x,y,w,h,
|
x,y,w,h,
|
||||||
layer.ptr);
|
layer.toStringz());
|
||||||
assert(widgetType(ptr) == "StaticText");
|
assert(widgetType(ptr) == "StaticText");
|
||||||
MWidget mw = new MWidget(ptr);
|
MWidget mw = new MWidget(ptr);
|
||||||
stack.pushObject(mw.mo);
|
stack.pushObject(mw.mo);
|
|
@ -213,7 +213,7 @@ void initializeInput()
|
||||||
{
|
{
|
||||||
// Move the player into place. TODO: This isn't really input-related
|
// Move the player into place. TODO: This isn't really input-related
|
||||||
// at all, and should be moved.
|
// at all, and should be moved.
|
||||||
with(playerData.position)
|
with(*playerData.position)
|
||||||
{
|
{
|
||||||
ogre_moveCamera(position[0], position[1], position[2]);
|
ogre_moveCamera(position[0], position[1], position[2]);
|
||||||
ogre_setCameraRotation(rotation[0], rotation[1], rotation[2]);
|
ogre_setCameraRotation(rotation[0], rotation[1], rotation[2]);
|
||||||
|
@ -305,6 +305,11 @@ extern(C) int d_frameStarted(float time, int guiMode)
|
||||||
bullet_getPlayerPos(&x, &y, &z);
|
bullet_getPlayerPos(&x, &y, &z);
|
||||||
ogre_moveCamera(x,y,z);
|
ogre_moveCamera(x,y,z);
|
||||||
|
|
||||||
|
// Store it in the player object
|
||||||
|
playerData.position.position[0] = x;
|
||||||
|
playerData.position.position[1] = y;
|
||||||
|
playerData.position.position[2] = z;
|
||||||
|
|
||||||
// Tell the sound scene that the player has moved
|
// Tell the sound scene that the player has moved
|
||||||
sndCumTime += time;
|
sndCumTime += time;
|
||||||
if(sndCumTime > sndRefresh)
|
if(sndCumTime > sndRefresh)
|
||||||
|
|
|
@ -1180,12 +1180,26 @@ class ExprStatement : Statement
|
||||||
// Require a terminating semicolon or line break
|
// Require a terminating semicolon or line break
|
||||||
bool term = true;
|
bool term = true;
|
||||||
|
|
||||||
|
// True if 'left' was set in the constructor
|
||||||
|
bool leftSet = false;
|
||||||
|
|
||||||
|
this(Expression lft=null)
|
||||||
|
{
|
||||||
|
left = lft;
|
||||||
|
if(left !is null)
|
||||||
|
leftSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
void parse(ref TokenArray toks)
|
void parse(ref TokenArray toks)
|
||||||
{
|
{
|
||||||
if(toks.length == 0)
|
if(left is null)
|
||||||
fail("Expected statement, found end of stream.");
|
{
|
||||||
loc = toks[0].loc;
|
if(toks.length == 0)
|
||||||
left = Expression.identify(toks);
|
fail("Expected statement, found end of stream.");
|
||||||
|
left = Expression.identify(toks);
|
||||||
|
}
|
||||||
|
|
||||||
|
loc = left.loc;
|
||||||
|
|
||||||
Token tok;
|
Token tok;
|
||||||
|
|
||||||
|
@ -1219,7 +1233,8 @@ class ExprStatement : Statement
|
||||||
|
|
||||||
void resolve(Scope sc)
|
void resolve(Scope sc)
|
||||||
{
|
{
|
||||||
left.resolve(sc);
|
if(!leftSet)
|
||||||
|
left.resolve(sc);
|
||||||
|
|
||||||
loc = left.loc;
|
loc = left.loc;
|
||||||
type = left.type;
|
type = left.type;
|
||||||
|
|
|
@ -989,26 +989,66 @@ class FunctionCallExpr : Expression
|
||||||
fail("Parameter list expected ')'", toks);
|
fail("Parameter list expected ')'", toks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special version of getParams that allow 'console-mode' grammar.
|
||||||
this(Expression func, ref TokenArray toks)
|
static void getParamsConsole(ref TokenArray toks,
|
||||||
|
out ExprArray parms,
|
||||||
|
out NamedParam[] named)
|
||||||
|
{
|
||||||
|
parms = null;
|
||||||
|
named = null;
|
||||||
|
|
||||||
|
// The param list is terminated by a semicolon or a newline
|
||||||
|
while(!isSep(toks))
|
||||||
|
{
|
||||||
|
if(toks.length == 0)
|
||||||
|
fail("Unexpected end of stream");
|
||||||
|
|
||||||
|
// Named paramter?
|
||||||
|
if(toks.length >= 3 && toks[1].type == TT.Equals)
|
||||||
|
{
|
||||||
|
NamedParam np;
|
||||||
|
|
||||||
|
reqNext(toks, TT.Identifier, np.name);
|
||||||
|
reqNext(toks, TT.Equals);
|
||||||
|
np.value = Expression.identify(toks);
|
||||||
|
|
||||||
|
named ~= np;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Normal parameter
|
||||||
|
if(named.length)
|
||||||
|
fail("Cannot use non-named parameters after a named one",
|
||||||
|
toks[0].loc);
|
||||||
|
|
||||||
|
parms ~= Expression.identify(toks);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow optional commas between parameters
|
||||||
|
isNext(toks, TT.Comma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this(Expression func, ref TokenArray toks, bool console=false)
|
||||||
{
|
{
|
||||||
assert(func !is null);
|
assert(func !is null);
|
||||||
fname = func;
|
fname = func;
|
||||||
loc = fname.loc;
|
loc = fname.loc;
|
||||||
|
|
||||||
// Parse the parameter list
|
// Parse the parameter list. The 'console' parameter determines
|
||||||
getParams(toks, params, named);
|
// whether we're using normal grammar rules:
|
||||||
|
// func(param1,param2)
|
||||||
|
// or console rules
|
||||||
|
// func param1 param2
|
||||||
|
if(console)
|
||||||
|
getParamsConsole(toks, params, named);
|
||||||
|
else
|
||||||
|
getParams(toks, params, named);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Might be used for D-like implicit function calling, eg. someFunc;
|
/* Might be used for D-like implicit function calling, eg. someFunc;
|
||||||
or (obj.prop)
|
or (obj.prop)
|
||||||
this(Expression func) {}
|
this(Expression func) {}
|
||||||
|
|
||||||
We might also allow a special free-form function call syntax, eg.
|
|
||||||
func 1 2 3
|
|
||||||
|
|
||||||
where parens and commas are optional, and the list is terminated by
|
|
||||||
isSep (newline or ;). This is useful mostly for console mode.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void parse(ref TokenArray toks) { assert(0); }
|
void parse(ref TokenArray toks) { assert(0); }
|
||||||
|
@ -1176,7 +1216,7 @@ class FunctionCallExpr : Expression
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate the parameters
|
// Evaluate the parameters
|
||||||
void evalParams()
|
private void evalParams()
|
||||||
{
|
{
|
||||||
// Again, let's handle the vararg case separately
|
// Again, let's handle the vararg case separately
|
||||||
if(isVararg)
|
if(isVararg)
|
||||||
|
@ -1253,9 +1293,10 @@ class FunctionCallExpr : Expression
|
||||||
{
|
{
|
||||||
if(isCast)
|
if(isCast)
|
||||||
{
|
{
|
||||||
|
// This is a type cast, not a function call.
|
||||||
|
|
||||||
// Just evaluate the expression. CastExpression takes care
|
// Just evaluate the expression. CastExpression takes care
|
||||||
// of everything automatically.
|
// of everything automatically.
|
||||||
|
|
||||||
assert(params.length == 1);
|
assert(params.length == 1);
|
||||||
assert(params[0] !is null);
|
assert(params[0] !is null);
|
||||||
params[0].eval();
|
params[0].eval();
|
||||||
|
|
|
@ -534,8 +534,8 @@ class DotOperator : OperatorExpr
|
||||||
type = member.type;
|
type = member.type;
|
||||||
|
|
||||||
// Make sure we only call static members when the owner is a
|
// Make sure we only call static members when the owner is a
|
||||||
// type.
|
// type or a package.
|
||||||
if(ot.isMeta && !member.isStatic)
|
if((ot.isMeta || ot.isPackage) && !member.isStatic)
|
||||||
fail("Can only access static members for " ~ owner.toString,
|
fail("Can only access static members for " ~ owner.toString,
|
||||||
loc);
|
loc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1702,11 +1702,21 @@ class TypeofType : ReplacerType
|
||||||
// D.
|
// D.
|
||||||
class GenericType : InternalType
|
class GenericType : InternalType
|
||||||
{
|
{
|
||||||
|
static GenericType sing;
|
||||||
|
|
||||||
this() { name = "var"; }
|
this() { name = "var"; }
|
||||||
|
|
||||||
static bool canParse(TokenArray toks)
|
static bool canParse(TokenArray toks)
|
||||||
{ return isNext(toks, TT.Var); }
|
{ return isNext(toks, TT.Var); }
|
||||||
|
|
||||||
|
static GenericType getSingleton()
|
||||||
|
{
|
||||||
|
if(sing is null)
|
||||||
|
sing = new GenericType;
|
||||||
|
|
||||||
|
return sing;
|
||||||
|
}
|
||||||
|
|
||||||
override:
|
override:
|
||||||
bool isVar() { return true; }
|
bool isVar() { return true; }
|
||||||
|
|
||||||
|
|
|
@ -576,6 +576,7 @@ class MemberExpr : Expression
|
||||||
isNext(toks, TT.Singleton) ||
|
isNext(toks, TT.Singleton) ||
|
||||||
isNext(toks, TT.State) ||
|
isNext(toks, TT.State) ||
|
||||||
isNext(toks, TT.Clone) ||
|
isNext(toks, TT.Clone) ||
|
||||||
|
isNext(toks, TT.Var) ||
|
||||||
isNext(toks, TT.Const);
|
isNext(toks, TT.Const);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,6 +804,13 @@ class MemberExpr : Expression
|
||||||
if(name.type == TT.Const || name.type == TT.Clone)
|
if(name.type == TT.Const || name.type == TT.Clone)
|
||||||
fail("Cannot use " ~ name.str ~ " as a variable", name.loc);
|
fail("Cannot use " ~ name.str ~ " as a variable", name.loc);
|
||||||
|
|
||||||
|
if(name.type == TT.Var)
|
||||||
|
{
|
||||||
|
type = GenericType.getSingleton();
|
||||||
|
vtype = VType.Special;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Look ourselves up in the local scope, and include imported
|
// Look ourselves up in the local scope, and include imported
|
||||||
// scopes.
|
// scopes.
|
||||||
look = sc.lookupImport(name);
|
look = sc.lookupImport(name);
|
||||||
|
@ -851,6 +859,9 @@ class MemberExpr : Expression
|
||||||
|
|
||||||
void evalAsm()
|
void evalAsm()
|
||||||
{
|
{
|
||||||
|
if(type.isVar)
|
||||||
|
fail("Cannot use 'var' as an expression", loc);
|
||||||
|
|
||||||
// Hairy. But does the trick for now.
|
// Hairy. But does the trick for now.
|
||||||
if(dotImport !is null && recurse)
|
if(dotImport !is null && recurse)
|
||||||
{
|
{
|
||||||
|
@ -1011,6 +1022,7 @@ class VarDeclStatement : Statement
|
||||||
{
|
{
|
||||||
VarDeclaration[] vars;
|
VarDeclaration[] vars;
|
||||||
bool reqSemi;
|
bool reqSemi;
|
||||||
|
Type preKnownType = null;
|
||||||
|
|
||||||
// Pass 'true' to the constructor to require a semi-colon (used eg
|
// Pass 'true' to the constructor to require a semi-colon (used eg
|
||||||
// in for loops)
|
// in for loops)
|
||||||
|
@ -1019,6 +1031,12 @@ class VarDeclStatement : Statement
|
||||||
reqSemi = rs;
|
reqSemi = rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used from the console, when the type is already known
|
||||||
|
this(Type type)
|
||||||
|
{
|
||||||
|
preKnownType = type;
|
||||||
|
}
|
||||||
|
|
||||||
static bool canParse(TokenArray toks)
|
static bool canParse(TokenArray toks)
|
||||||
{
|
{
|
||||||
if(Type.canParseRem(toks) &&
|
if(Type.canParseRem(toks) &&
|
||||||
|
@ -1030,7 +1048,12 @@ class VarDeclStatement : Statement
|
||||||
void parse(ref TokenArray toks)
|
void parse(ref TokenArray toks)
|
||||||
{
|
{
|
||||||
VarDeclaration varDec;
|
VarDeclaration varDec;
|
||||||
varDec = new VarDeclaration;
|
|
||||||
|
if(preKnownType !is null)
|
||||||
|
varDec = new VarDeclaration(preKnownType);
|
||||||
|
else
|
||||||
|
varDec = new VarDeclaration;
|
||||||
|
|
||||||
varDec.parse(toks);
|
varDec.parse(toks);
|
||||||
vars ~= varDec;
|
vars ~= varDec;
|
||||||
loc = varDec.var.name.loc;
|
loc = varDec.var.name.loc;
|
||||||
|
|
|
@ -134,19 +134,16 @@ class Console
|
||||||
|
|
||||||
void putln(char[] str) { put(str, true); }
|
void putln(char[] str) { put(str, true); }
|
||||||
|
|
||||||
Statement[] parse(TokenArray toks)
|
Statement[] parse(TokenArray toks, Scope sc)
|
||||||
{
|
{
|
||||||
Statement b = null;
|
Statement b;
|
||||||
Statement[] res;
|
Statement[] res;
|
||||||
|
|
||||||
repeat:
|
repeat:
|
||||||
|
|
||||||
if(VarDeclStatement.canParse(toks))
|
b = null;
|
||||||
{
|
|
||||||
if(!allowVar) fail("Variable declaration not allowed here");
|
if(CodeBlock.canParse(toks)) b = new CodeBlock;
|
||||||
b = new VarDeclStatement;
|
|
||||||
}
|
|
||||||
else if(CodeBlock.canParse(toks)) b = new CodeBlock;
|
|
||||||
else if(IfStatement.canParse(toks)) b = new IfStatement;
|
else if(IfStatement.canParse(toks)) b = new IfStatement;
|
||||||
else if(DoWhileStatement.canParse(toks)) b = new DoWhileStatement;
|
else if(DoWhileStatement.canParse(toks)) b = new DoWhileStatement;
|
||||||
else if(WhileStatement.canParse(toks)) b = new WhileStatement;
|
else if(WhileStatement.canParse(toks)) b = new WhileStatement;
|
||||||
|
@ -154,11 +151,24 @@ class Console
|
||||||
else if(ForeachStatement.canParse(toks)) b = new ForeachStatement;
|
else if(ForeachStatement.canParse(toks)) b = new ForeachStatement;
|
||||||
else if(ImportStatement.canParse(toks)) b = new ImportStatement(true);
|
else if(ImportStatement.canParse(toks)) b = new ImportStatement(true);
|
||||||
|
|
||||||
// If this is not one of the above, default to an expression
|
if(b !is null)
|
||||||
// statement.
|
{
|
||||||
else b = new ExprStatement;
|
// Parse and resolve
|
||||||
|
b.parse(toks);
|
||||||
|
b.resolve(sc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If this is not one of the above, default to a console
|
||||||
|
// statement.
|
||||||
|
auto es = new ConsoleStatement;
|
||||||
|
b = es;
|
||||||
|
|
||||||
b.parse(toks);
|
// Parse and resolve in one operation.
|
||||||
|
es.parseResolve(toks, sc, allowVar);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(b !is null);
|
||||||
res ~= b;
|
res ~= b;
|
||||||
|
|
||||||
// Are there more tokens waiting for us?
|
// Are there more tokens waiting for us?
|
||||||
|
@ -269,51 +279,58 @@ class Console
|
||||||
if(tokArr.length == 0)
|
if(tokArr.length == 0)
|
||||||
return CR.Empty;
|
return CR.Empty;
|
||||||
|
|
||||||
// Phase II, parse
|
// Phase II & III, parse and resolve
|
||||||
TokenArray toks = tokArr.arrayCopy();
|
TokenArray toks = tokArr.arrayCopy();
|
||||||
Statement[] sts = parse(toks);
|
Statement[] sts = parse(toks, sc);
|
||||||
delete toks;
|
delete toks;
|
||||||
assert(sts.length >= 1);
|
assert(sts.length >= 1);
|
||||||
|
|
||||||
// First, background the current thread (if any) and bring up
|
// First, background the current thread (if any) and bring up
|
||||||
// our own.
|
// our own. This is necessary in order to keep the stack
|
||||||
|
// variables we make.
|
||||||
store = cthread;
|
store = cthread;
|
||||||
if(store !is null)
|
if(store !is null)
|
||||||
store.background();
|
store.background();
|
||||||
assert(trd !is null);
|
assert(trd !is null);
|
||||||
trd.foreground();
|
trd.foreground();
|
||||||
|
|
||||||
// We have to push ourselves on the function stack, or call()
|
// We have to push ourselves on the function stack, or
|
||||||
// will see that it's empty and kill the thread upon exit
|
// Function.call() will see that it's empty and kill the thread
|
||||||
|
// upon exit
|
||||||
trd.fstack.pushExt("Console");
|
trd.fstack.pushExt("Console");
|
||||||
|
|
||||||
// The rest must be performed separately for each statement on
|
// The rest must be performed separately for each statement on
|
||||||
// the line.
|
// the line.
|
||||||
foreach(st; sts)
|
foreach(st; sts)
|
||||||
{
|
{
|
||||||
// Phase III, resolve
|
|
||||||
st.resolve(sc);
|
|
||||||
|
|
||||||
// Phase IV, compile
|
// Phase IV, compile
|
||||||
tasm.newFunc();
|
tasm.newFunc();
|
||||||
|
|
||||||
// Is it an expression?
|
ExprStatement es;
|
||||||
auto es = cast(ExprStatement)st;
|
|
||||||
if(es !is null)
|
// Is it an special console statement?
|
||||||
|
auto cs = cast(ConsoleStatement)st;
|
||||||
|
if(cs !is null)
|
||||||
{
|
{
|
||||||
// Yes. But is the type usable?
|
// Yes. Is the client an expression?
|
||||||
if(es.left.type.canCastTo(ArrayType.getString())
|
es = cast(ExprStatement)cs.client;
|
||||||
&& es.right is null)
|
if(es !is null)
|
||||||
{
|
{
|
||||||
// Yup. Get the type, and cast the expression to string.
|
// Ok. But is the type usable?
|
||||||
scope auto ce = new
|
if(es.left.type.canCastTo(ArrayType.getString())
|
||||||
CastExpression(es.left, ArrayType.getString());
|
&& es.right is null)
|
||||||
ce.eval();
|
{
|
||||||
|
// Yup. Get the type, and cast the expression to string.
|
||||||
|
scope auto ce = new
|
||||||
|
CastExpression(es.left, ArrayType.getString());
|
||||||
|
ce.eval();
|
||||||
|
}
|
||||||
|
else es = null;
|
||||||
}
|
}
|
||||||
else es = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// No expression is being used, so compile the statement
|
// No expression is being used, so compile the statement
|
||||||
|
// normally.
|
||||||
if(es is null)
|
if(es is null)
|
||||||
st.compile();
|
st.compile();
|
||||||
|
|
||||||
|
@ -336,28 +353,31 @@ class Console
|
||||||
// function frame, ie. the same way we treat function
|
// function frame, ie. the same way we treat function
|
||||||
// parameters. We do this by giving the variables negative
|
// parameters. We do this by giving the variables negative
|
||||||
// indices.
|
// indices.
|
||||||
auto vs = cast(VarDeclStatement)st;
|
if(cs !is null)
|
||||||
if(vs !is null)
|
|
||||||
{
|
{
|
||||||
// Add the new vars to the list
|
auto vs = cast(VarDeclStatement)cs.client;
|
||||||
foreach(v; vs.vars)
|
if(vs !is null)
|
||||||
{
|
{
|
||||||
varList ~= v.var;
|
// Add the new vars to the list
|
||||||
|
foreach(v; vs.vars)
|
||||||
|
{
|
||||||
|
varList ~= v.var;
|
||||||
|
|
||||||
// Add the size as well
|
// Add the size as well
|
||||||
varSize += v.var.type.getSize;
|
varSize += v.var.type.getSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recalculate all the indices backwards from zero
|
||||||
|
int place = 0;
|
||||||
|
foreach_reverse(v; varList)
|
||||||
|
{
|
||||||
|
place -= v.type.getSize;
|
||||||
|
v.number = place;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the scope stack counters
|
||||||
|
sc.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recalculate all the indices backwards from zero
|
|
||||||
int place = 0;
|
|
||||||
foreach_reverse(v; varList)
|
|
||||||
{
|
|
||||||
place -= v.type.getSize;
|
|
||||||
v.number = place;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the scope stack counters
|
|
||||||
sc.reset();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,3 +463,71 @@ class Console
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Statement that handles variable declarations, function calls and
|
||||||
|
// expression statements in consoles. Since these are gramatically
|
||||||
|
// similar, we need the type to determine which
|
||||||
|
class ConsoleStatement : Statement
|
||||||
|
{
|
||||||
|
// Used for variables and expression statements
|
||||||
|
Statement client;
|
||||||
|
|
||||||
|
// Used for function calls
|
||||||
|
FunctionCallExpr func;
|
||||||
|
|
||||||
|
void parseResolve(ref TokenArray toks, Scope sc, bool allowVar)
|
||||||
|
{
|
||||||
|
assert(toks.length != 0);
|
||||||
|
|
||||||
|
// Get the first expression
|
||||||
|
auto first = Expression.identify(toks);
|
||||||
|
|
||||||
|
// And the type right away
|
||||||
|
first.resolve(sc);
|
||||||
|
auto type = first.type;
|
||||||
|
assert(type !is null);
|
||||||
|
|
||||||
|
// Type? If so, it's a variable declaration
|
||||||
|
if((type.isMeta || type.isVar) && allowVar)
|
||||||
|
{
|
||||||
|
if(type.isMeta) type = type.getBase();
|
||||||
|
|
||||||
|
client = new VarDeclStatement(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function?
|
||||||
|
else if(type.isFunc)
|
||||||
|
func = new FunctionCallExpr(first, toks, true);
|
||||||
|
|
||||||
|
// It's an expression statement
|
||||||
|
else
|
||||||
|
client = new ExprStatement(first);
|
||||||
|
|
||||||
|
if(client !is null)
|
||||||
|
{
|
||||||
|
client.parse(toks);
|
||||||
|
client.resolve(sc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(func !is null);
|
||||||
|
func.resolve(sc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override:
|
||||||
|
void parse(ref TokenArray) { assert(0); }
|
||||||
|
void resolve(Scope sc) { assert(0); }
|
||||||
|
|
||||||
|
void compile()
|
||||||
|
{
|
||||||
|
if(client !is null)
|
||||||
|
{
|
||||||
|
client.compile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(func !is null);
|
||||||
|
func.evalPop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -116,9 +116,13 @@ long execLimit = 10000000;
|
||||||
bool defaultLogToStdout = false;
|
bool defaultLogToStdout = false;
|
||||||
|
|
||||||
// If true, all function stack operations (pushes and pops) are logged
|
// If true, all function stack operations (pushes and pops) are logged
|
||||||
// with dbg.log().
|
// with dbg.log(), and all logged messages are indented according to
|
||||||
|
// the current fstack level.
|
||||||
bool logFStack = true;
|
bool logFStack = true;
|
||||||
|
|
||||||
|
// If true, log when threads are put into the background/forground.
|
||||||
|
bool logThreads = true;
|
||||||
|
|
||||||
/*********************************************************
|
/*********************************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,9 @@ struct Thread
|
||||||
list.remove(this);
|
list.remove(this);
|
||||||
list = null;
|
list = null;
|
||||||
assert(isDead);
|
assert(isDead);
|
||||||
|
|
||||||
|
static if(logThreads)
|
||||||
|
dbg.log(format("------ killing thread=%s ------", getIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop the execution of a thread and cancel any scheduling.
|
// Stop the execution of a thread and cancel any scheduling.
|
||||||
|
|
31
mscripts/console.mn
Normal file
31
mscripts/console.mn
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
OpenMW - The completely unofficial reimplementation of Morrowind
|
||||||
|
Copyright (C) 2008 Nicolay Korslund
|
||||||
|
Email: < korslund@gmail.com >
|
||||||
|
WWW: http://openmw.snaptoad.com/
|
||||||
|
|
||||||
|
This file (console.mn) is part of the OpenMW package.
|
||||||
|
|
||||||
|
OpenMW is distributed as free software: you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License
|
||||||
|
version 3, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
version 3 along with this program. If not, see
|
||||||
|
http://www.gnu.org/licenses/ .
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Console
|
||||||
|
|
||||||
|
|
||||||
|
// This class contains all the functions available to the ingame
|
||||||
|
// console.
|
||||||
|
|
||||||
|
import io;
|
||||||
|
import game;
|
25
mscripts/game/npc.mn
Normal file
25
mscripts/game/npc.mn
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
OpenMW - The completely unofficial reimplementation of Morrowind
|
||||||
|
Copyright (C) 2008 Nicolay Korslund
|
||||||
|
Email: < korslund@gmail.com >
|
||||||
|
WWW: http://openmw.snaptoad.com/
|
||||||
|
|
||||||
|
This file (npc.mn) is part of the OpenMW package.
|
||||||
|
|
||||||
|
OpenMW is distributed as free software: you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License
|
||||||
|
version 3, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
version 3 along with this program. If not, see
|
||||||
|
http://www.gnu.org/licenses/ .
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
class NPC : Person
|
||||||
|
|
27
mscripts/game/player.mn
Normal file
27
mscripts/game/player.mn
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
OpenMW - The completely unofficial reimplementation of Morrowind
|
||||||
|
Copyright (C) 2008 Nicolay Korslund
|
||||||
|
Email: < korslund@gmail.com >
|
||||||
|
WWW: http://openmw.snaptoad.com/
|
||||||
|
|
||||||
|
This file (player.mn) is part of the OpenMW package.
|
||||||
|
|
||||||
|
OpenMW is distributed as free software: you can redistribute it
|
||||||
|
and/or modify it under the terms of the GNU General Public License
|
||||||
|
version 3, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
version 3 along with this program. If not, see
|
||||||
|
http://www.gnu.org/licenses/ .
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
singleton player : Person
|
||||||
|
|
||||||
|
name="Player Name"
|
||||||
|
level = 5 // Just an example value
|
|
@ -28,9 +28,11 @@ import monster.compiler.scopes : global;
|
||||||
import monster.modules.timer;
|
import monster.modules.timer;
|
||||||
|
|
||||||
import core.config;
|
import core.config;
|
||||||
import ogre.gui;
|
import gui.gui;
|
||||||
|
import scene.player;
|
||||||
|
|
||||||
import std.string;
|
import std.string;
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
// Set up the base Monster classes we need in OpenMW
|
// Set up the base Monster classes we need in OpenMW
|
||||||
void initMonsterScripts()
|
void initMonsterScripts()
|
||||||
|
@ -45,6 +47,9 @@ void initMonsterScripts()
|
||||||
// Get the Config singleton object
|
// Get the Config singleton object
|
||||||
config.mo = vm.load("Config").getSing();
|
config.mo = vm.load("Config").getSing();
|
||||||
|
|
||||||
|
// Set up the player object.
|
||||||
|
playerData.setup();
|
||||||
|
|
||||||
// Set up the GUI Monster module
|
// Set up the GUI Monster module
|
||||||
setupGUIScripts();
|
setupGUIScripts();
|
||||||
}
|
}
|
||||||
|
@ -62,7 +67,6 @@ void runGUIScripts()
|
||||||
|
|
||||||
// This should probably not be here:
|
// This should probably not be here:
|
||||||
import monster.vm.dbg;
|
import monster.vm.dbg;
|
||||||
import std.string;
|
|
||||||
|
|
||||||
extern(C):
|
extern(C):
|
||||||
void dbg_trace(char*str) { dbg.trace(toString(str)); }
|
void dbg_trace(char*str) { dbg.trace(toString(str)); }
|
||||||
|
|
|
@ -164,28 +164,3 @@ void ogre_moveCameraRel(float x, float y, float z);
|
||||||
|
|
||||||
// Insert a raw RGBA image into the texture system.
|
// Insert a raw RGBA image into the texture system.
|
||||||
//void ogre_insertTexture(char *name, int width, int height, void *data);
|
//void ogre_insertTexture(char *name, int width, int height, void *data);
|
||||||
|
|
||||||
// GUI functions. Under development.
|
|
||||||
typedef void* WidgetPtr;
|
|
||||||
void gui_setupGUI(int debugOut);
|
|
||||||
void gui_toggleGui();
|
|
||||||
void gui_setCellName(char *str);
|
|
||||||
|
|
||||||
// Get the widget type, as a string
|
|
||||||
char *gui_widgetType(WidgetPtr);
|
|
||||||
|
|
||||||
// Get the height or width of a widget. If the argument is null,
|
|
||||||
// return the size of the screen.
|
|
||||||
int gui_getHeight(WidgetPtr);
|
|
||||||
int gui_getWidth(WidgetPtr);
|
|
||||||
|
|
||||||
// Set various properties of a given widget
|
|
||||||
void gui_setCaption(WidgetPtr, char*);
|
|
||||||
void gui_setNeedMouseFocus(WidgetPtr, int);
|
|
||||||
void gui_setTextColor(WidgetPtr, float,float,float);
|
|
||||||
void gui_setCoord(WidgetPtr, int,int,int,int);
|
|
||||||
|
|
||||||
// Various ways to get or create widgets
|
|
||||||
WidgetPtr gui_loadLayout(char *file, char *prefix, WidgetPtr parent);
|
|
||||||
WidgetPtr gui_getChild(WidgetPtr, char*);
|
|
||||||
WidgetPtr gui_createText(char *skin, int x, int y, int w, int h, char *layer);
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ extern "C" int32_t ogre_configure(
|
||||||
{
|
{
|
||||||
// Set up logging first
|
// Set up logging first
|
||||||
new LogManager;
|
new LogManager;
|
||||||
Log *log = LogManager::getSingleton().createLog("default");
|
Log *log = LogManager::getSingleton().createLog("Ogre.log");
|
||||||
|
|
||||||
if(debugOut)
|
if(debugOut)
|
||||||
// Full log detail
|
// Full log detail
|
||||||
|
|
|
@ -24,7 +24,9 @@ extern "C" int32_t gui_getWidth(MyGUI::WidgetPtr p)
|
||||||
|
|
||||||
// Set various properties of a given widget
|
// Set various properties of a given widget
|
||||||
extern "C" void gui_setCaption(MyGUI::WidgetPtr p, char* s)
|
extern "C" void gui_setCaption(MyGUI::WidgetPtr p, char* s)
|
||||||
{ p->setCaption(s); }
|
{
|
||||||
|
p->setCaption(s);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void gui_setNeedMouseFocus(MyGUI::WidgetPtr p, int32_t b)
|
extern "C" void gui_setNeedMouseFocus(MyGUI::WidgetPtr p, int32_t b)
|
||||||
{ p->setNeedMouseFocus(b); }
|
{ p->setNeedMouseFocus(b); }
|
||||||
|
|
1
openmw.d
1
openmw.d
|
@ -30,6 +30,7 @@ import std.file;
|
||||||
|
|
||||||
import ogre.ogre;
|
import ogre.ogre;
|
||||||
import ogre.bindings;
|
import ogre.bindings;
|
||||||
|
import gui.bindings;
|
||||||
|
|
||||||
import bullet.bullet;
|
import bullet.bullet;
|
||||||
|
|
||||||
|
|
|
@ -453,7 +453,7 @@ class CellData
|
||||||
{
|
{
|
||||||
// Create a creature, based on current player level.
|
// Create a creature, based on current player level.
|
||||||
LiveCreature ls;
|
LiveCreature ls;
|
||||||
ls.m = l.instCreature(playerData.level);
|
ls.m = l.instCreature(*playerData.level);
|
||||||
if(ls.m != null)
|
if(ls.m != null)
|
||||||
{
|
{
|
||||||
// Note that this clones a creature object, not a
|
// Note that this clones a creature object, not a
|
||||||
|
@ -565,7 +565,7 @@ class CellData
|
||||||
if(door && !playerData.posSet)
|
if(door && !playerData.posSet)
|
||||||
{
|
{
|
||||||
playerData.posSet = true;
|
playerData.posSet = true;
|
||||||
playerData.position = *pos;
|
*playerData.position = *pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // End of while(hasMoreSubs)
|
} // End of while(hasMoreSubs)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
module scene.player;
|
module scene.player;
|
||||||
|
|
||||||
import ogre.ogre;
|
import ogre.ogre;
|
||||||
|
import monster.monster;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Contains essential data about the player and other current game
|
* Contains essential data about the player and other current game
|
||||||
|
@ -34,14 +35,30 @@ PlayerData playerData;
|
||||||
|
|
||||||
struct PlayerData
|
struct PlayerData
|
||||||
{
|
{
|
||||||
// Position and rotation. The rotation is not updated continuously,
|
MonsterObject *mo;
|
||||||
// only the position.
|
|
||||||
Placement position;
|
|
||||||
|
|
||||||
// Just an example value, we use it for resolving leveled lists
|
Placement *position;
|
||||||
// (lists that determine eg. what creatures to put in a cave based
|
int *level;
|
||||||
// on what level the player is.)
|
|
||||||
short level = 5;
|
// Set up the player object. This is still pretty hackish and
|
||||||
|
// temporary.
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
assert(mo is null);
|
||||||
|
mo = vm.load("game.player").createObject;
|
||||||
|
level = mo.getIntPtr("level");
|
||||||
|
|
||||||
|
// Still an ugly hack
|
||||||
|
position = cast(Placement*)mo.getFloatPtr("x");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
char[] getName()
|
||||||
|
{
|
||||||
|
assert(mo !is null);
|
||||||
|
return mo.getString8("name");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Temp. way of selecting start point - used in celldata
|
// Temp. way of selecting start point - used in celldata
|
||||||
bool posSet = false;
|
bool posSet = false;
|
||||||
|
|
Loading…
Reference in a new issue