Made the first working Monster script within OpenMW

git-svn-id: https://openmw.svn.sourceforge.net/svnroot/openmw/trunk@62 ea6a568a-9f4f-0410-981a-c910a81bb256
This commit is contained in:
nkorslund 2008-11-07 13:14:46 +00:00
parent 3f1aeb3aef
commit 7349221b9c
27 changed files with 261 additions and 43 deletions

View file

@ -35,6 +35,8 @@ import scene.player;
import bullet.bindings;
import monster.monster;
import ogre.bindings;
import input.keys;
@ -290,6 +292,9 @@ extern(C) int d_frameStarted(float time)
if(doExit) return 0;
// Run the Monster scheduler
scheduler.doFrame();
musCumTime += time;
if(musCumTime > musRefresh)
{

View file

@ -24,8 +24,8 @@
module monster.compiler.assembler;
import monster.minibos.string;
import monster.minibos.stdio;
import std.string;
import std.stdio;
import monster.util.list;

View file

@ -38,9 +38,9 @@ import monster.vm.mclass;
import monster.vm.arrays;
import monster.util.list;
import monster.minibos.string;
import monster.minibos.stdio;
import monster.minibos.utf : decode, toUTF32;
import std.string;
import std.stdio;
import std.utf : decode, toUTF32;
alias Expression[] ExprArray;

View file

@ -50,7 +50,7 @@ import monster.vm.mclass;
import monster.vm.error;
import monster.vm.fstack;
import monster.minibos.stdio;
import std.stdio;
// One problem with these split compiler / vm classes is that we
// likely end up with data (or at least pointers) we don't need, and a

View file

@ -32,7 +32,7 @@ import monster.compiler.types;
import monster.vm.error;
import monster.vm.arrays;
import monster.minibos.stdio;
import std.stdio;
// Handles - ! ++ --
class UnaryOperator : Expression

View file

@ -27,7 +27,7 @@ import monster.compiler.scopes;
import monster.compiler.types;
import monster.compiler.assembler;
import monster.minibos.stdio;
import std.stdio;
/* This module contains special scopes for builtin types. These are
used to resolve type properties like .length for arrays and .min

View file

@ -23,8 +23,8 @@
module monster.compiler.scopes;
import monster.minibos.stdio;
import monster.minibos.string;
import std.stdio;
import std.string;
import monster.util.aa;

View file

@ -24,8 +24,8 @@
module monster.compiler.statement;
import monster.minibos.string;
import monster.minibos.stdio;
import std.string;
import std.stdio;
import monster.compiler.tokenizer;
import monster.compiler.expression;

View file

@ -34,7 +34,7 @@ import monster.vm.error;
import monster.util.aa;
import monster.minibos.stdio;
import std.stdio;
struct State
{

View file

@ -24,9 +24,9 @@
module monster.compiler.tokenizer;
import monster.minibos.string;
import monster.minibos.stream;
import monster.minibos.stdio;
import std.string;
import std.stream;
import std.stdio;
import monster.util.string : begins;

View file

@ -35,8 +35,8 @@ import monster.compiler.states;
import monster.vm.mclass;
import monster.vm.error;
import monster.minibos.stdio;
import monster.minibos.string;
import std.stdio;
import std.string;
/*
List of all type classes:

View file

@ -30,8 +30,8 @@ import monster.compiler.expression;
import monster.compiler.scopes;
import monster.compiler.block;
import monster.minibos.string;
import monster.minibos.stdio;
import std.string;
import std.stdio;
import monster.vm.error;
enum VarType

View file

@ -27,9 +27,9 @@ import monster.util.freelist;
import monster.util.flags;
import monster.vm.error;
import monster.minibos.string;
import monster.minibos.uni;
import monster.minibos.stdio;
import std.string;
import std.uni;
import std.stdio;
// An index to an array. Array indices may be 0, unlike object indices
// which span from 1 and upwards, and has 0 as the illegal 'null'

View file

@ -24,8 +24,8 @@
module monster.vm.codestream;
import monster.minibos.string;
import monster.minibos.stdio;
import std.string;
import std.stdio;
import monster.vm.error;
import monster.compiler.linespec;

View file

@ -26,7 +26,7 @@ module monster.vm.error;
import monster.compiler.tokenizer;
version(Tango) import tango.core.Exception;
import monster.minibos.string;
import std.string;
class MonsterException : Exception
{

View file

@ -30,8 +30,8 @@ import monster.vm.mclass;
import monster.vm.mobject;
import monster.util.flags;
import monster.minibos.string;
import monster.minibos.stdio;
import std.string;
import std.stdio;
// An iterator index.
typedef int IIndex;

View file

@ -45,10 +45,10 @@ import monster.util.flags;
import monster.util.freelist;
import monster.util.string;
import monster.minibos.string;
import monster.minibos.stdio;
import monster.minibos.file;
import monster.minibos.stream;
import std.string;
import std.stdio;
import std.file;
import std.stream;
// TODO: Needed to fix DMD/GDC template problems. Remove if this bug
// is fixed.

View file

@ -32,9 +32,9 @@ import monster.compiler.states;
import monster.compiler.variables;
import monster.compiler.scopes;
import monster.minibos.string;
import monster.minibos.stdio;
import monster.minibos.utf;
import std.string;
import std.stdio;
import std.utf;
// An index to a monster object.
typedef int MIndex;

View file

@ -32,7 +32,7 @@ import monster.vm.error;
import monster.vm.fstack;
import monster.util.freelist;
import monster.minibos.string;
import std.string;
// Enable minor safety checks - can be removed from release code.
debug=safecheck;

View file

@ -24,9 +24,9 @@
module monster.vm.stack;
import monster.minibos.string;
import monster.minibos.stdio;
import monster.minibos.utf;
import std.string;
import std.stdio;
import std.utf;
import monster.compiler.scopes;

View file

@ -23,10 +23,10 @@
module monster.vm.vm;
import monster.minibos.string;
import monster.minibos.stdio;
import monster.minibos.uni;
import monster.minibos.c.string;
import std.string;
import std.stdio;
import std.uni;
import std.c.string;
import monster.compiler.bytecode;
import monster.compiler.linespec;

70
mscripts/object.d Normal file
View file

@ -0,0 +1,70 @@
module mscripts.object;
import monster.monster;
import std.stdio;
import std.date;
// Set up the base Monster classes we need in OpenMW
void initMonsterScripts()
{
// Add the script directory
MonsterClass.addPath("mscripts/");
// Make sure the Object class is loaded
auto mc = new MonsterClass("Object", "object.mn");
// Bind various functions
mc.bind("print", { print(); });
mc.bind("sleep", new IdleSleep);
// Load and run the test script
mc = new MonsterClass("Test");
mc.createObject().call("test");
}
// Write a message to screen
void print()
{
AIndex[] args = stack.popAArray();
foreach(AIndex ind; args)
writef("%s ", arrays.getRef(ind).carr);
writefln();
}
// Sleep a given amount of time. Currently uses the system clock, but
// will later be optimized to use the already existing timing
// information from OGRE.
class IdleSleep : IdleFunction
{
long getLong(MonsterObject *mo)
{ return *(cast(long*)mo.extra); }
void setLong(MonsterObject *mo, long l)
{ *(cast(long*)mo.extra) = l; }
override:
bool initiate(MonsterObject *mo)
{
// Get the parameter
double secs = stack.popFloat;
// Get current time
long newTime = getUTCtime();
// Calculate when we should return
newTime += secs*TicksPerSecond;
// Store it
if(mo.extra == null) mo.extra = new long;
setLong(mo, newTime);
// Schedule us
return true;
}
bool hasFinished(MonsterObject *mo)
{
// Is it time?
return getUTCtime() >= getLong(mo);
}
}

8
mscripts/object.mn Normal file
View file

@ -0,0 +1,8 @@
// This is the base class of all OpenMW Monster classes.
class Object;
// Sleeps a given amount of time
idle sleep(float seconds);
// Print a message to screen
native print(char[][] msg...);

17
mscripts/test.mn Normal file
View file

@ -0,0 +1,17 @@
// A sample class
class Test : Object;
test()
{
state = printMessage;
}
state printMessage
{
// This state code will run as long as the object is in this state.
begin:
sleep(10);
print("Howdy from the world of Monster scripts!");
print("This script is located in mscripts/test.mn. Check it out!");
goto begin;
}

View file

@ -41,6 +41,7 @@ import core.memory;
import core.config;
import monster.util.string;
import mscripts.object;
import sound.audio;
@ -125,6 +126,7 @@ void main(char[][] args)
}
initializeMemoryRegions();
initMonsterScripts();
/*
importSavegame("data/quiksave.ess");

View file

@ -26,6 +26,8 @@ module sound.audio;
public import sound.sfx;
public import sound.music;
import monster.monster;
import sound.al;
import sound.alc;

114
util/utfconvert.d Normal file
View file

@ -0,0 +1,114 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.snaptoad.com/
This file (utfconvert.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 util.utfconvert;
import std.utf;
// A specialized version of std.utf.decode(). It returns a bool rather
// than throwing an exception.
private bool fdecode(char[] s, inout size_t idx)
{
size_t len = s.length;
dchar V;
size_t i = idx;
char u = s[i];
if (u & 0x80)
{ uint n;
char u2;
/* The following encodings are valid, except for the 5 and 6 byte
* combinations:
* 0xxxxxxx
* 110xxxxx 10xxxxxx
* 1110xxxx 10xxxxxx 10xxxxxx
* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
*/
for (n = 1; ; n++)
{
if (n > 4)
return false; // only do the first 4 of 6 encodings
if (((u << n) & 0x80) == 0)
{
if (n == 1)
return false;
break;
}
}
// Pick off (7 - n) significant bits of B from first byte of octet
V = cast(dchar)(u & ((1 << (7 - n)) - 1));
if (i + (n - 1) >= len)
return false; // off end of string
/* The following combinations are overlong, and illegal:
* 1100000x (10xxxxxx)
* 11100000 100xxxxx (10xxxxxx)
* 11110000 1000xxxx (10xxxxxx 10xxxxxx)
* 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
* 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
*/
u2 = s[i + 1];
if ((u & 0xFE) == 0xC0 ||
(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
(u == 0xFC && (u2 & 0xFC) == 0x80))
return false; // overlong combination
for (uint j = 1; j != n; j++)
{
u = s[i + j];
if ((u & 0xC0) != 0x80)
return false; // trailing bytes are 10xxxxxx
V = (V << 6) | (u & 0x3F);
}
if (!isValidDchar(V))
return false;
i += n;
}
else
{
V = cast(dchar) u;
i++;
}
idx = i;
return true;
}
// Converts any string to valid UTF8 so it can be safely printed. It
// does not translate from other encodings but simply replaces invalid
// characters with 'replace'. Does everything in place.
char[] makeUTF8(char[] str, char replace = '?')
{
size_t idx = 0;
while(idx < str.length)
if(!fdecode(str, idx))
str[idx++] = replace;
return str;
}