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
pull/7/head
nkorslund 16 years ago
parent 3f1aeb3aef
commit 7349221b9c

@ -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)
{

@ -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;

@ -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;

@ -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

@ -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

@ -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

@ -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;

@ -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;

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

@ -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;

@ -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:

@ -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

@ -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'

@ -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;

@ -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
{

@ -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;

@ -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.

@ -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;

@ -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;

@ -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;

@ -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;

@ -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);
}
}

@ -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...);

@ -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;
}

@ -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");

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

@ -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;
}
Loading…
Cancel
Save