forked from mirror/openmw-tes3mp
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:
parent
3f1aeb3aef
commit
7349221b9c
27 changed files with 261 additions and 43 deletions
|
@ -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;
|
||||
|
|
70
mscripts/object.d
Normal file
70
mscripts/object.d
Normal 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
8
mscripts/object.mn
Normal 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
17
mscripts/test.mn
Normal 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;
|
||||
}
|
2
openmw.d
2
openmw.d
|
@ -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;
|
||||
|
||||
|
|
114
util/utfconvert.d
Normal file
114
util/utfconvert.d
Normal 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;
|
||||
}
|
Loading…
Reference in a new issue