mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-07-21 05:14:10 +00:00
Started implementing ALL in-game objects as Monster scripts.
git-svn-id: https://openmw.svn.sourceforge.net/svnroot/openmw/trunk@72 ea6a568a-9f4f-0410-981a-c910a81bb256
This commit is contained in:
parent
c2d992c8f0
commit
76295fbd45
35 changed files with 466 additions and 62 deletions
48
esm/defs.d
48
esm/defs.d
|
@ -25,6 +25,7 @@ module esm.defs;
|
||||||
|
|
||||||
public import std.string;
|
public import std.string;
|
||||||
public import monster.util.string;
|
public import monster.util.string;
|
||||||
|
import monster.monster;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Types and definitions related to parsing esm and esp files
|
* Types and definitions related to parsing esm and esp files
|
||||||
|
@ -135,3 +136,50 @@ align(1) struct ENAMstruct
|
||||||
|
|
||||||
static assert(ENAMstruct.sizeof==24);
|
static assert(ENAMstruct.sizeof==24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Common stuff for all the load* structs
|
||||||
|
template LoadTT(T)
|
||||||
|
{
|
||||||
|
LoadState state;
|
||||||
|
char[] name, id;
|
||||||
|
|
||||||
|
MonsterObject *proto;
|
||||||
|
static MonsterClass mc;
|
||||||
|
|
||||||
|
void makeProto(char[] clsName = null)
|
||||||
|
{
|
||||||
|
// Use the template type name as the Monster class name if none
|
||||||
|
// is specified.
|
||||||
|
if(clsName == "")
|
||||||
|
{
|
||||||
|
clsName = typeid(T).toString;
|
||||||
|
|
||||||
|
// Remove the module name
|
||||||
|
int i = clsName.rfind('.');
|
||||||
|
if(i != -1)
|
||||||
|
clsName = clsName[i+1..$];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up a prototype object
|
||||||
|
if(mc is null)
|
||||||
|
mc = MonsterClass.find(clsName);
|
||||||
|
proto = mc.createObject();
|
||||||
|
|
||||||
|
proto.setString8("id", id);
|
||||||
|
proto.setString8("name", name);
|
||||||
|
|
||||||
|
static if(is(typeof(data.weight) == float))
|
||||||
|
{
|
||||||
|
proto.setFloat("weight", data.weight);
|
||||||
|
proto.setInt("value", data.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static if(is(typeof(data.enchant)==int))
|
||||||
|
proto.setInt("enchant", data.enchant);
|
||||||
|
|
||||||
|
static if(is(typeof(data.health)==int))
|
||||||
|
proto.setInt("health", data.health);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template LoadT() { mixin LoadTT!(typeof(*this)); }
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
module esm.imports;
|
module esm.imports;
|
||||||
|
|
||||||
/* This is a file that imports common modules used by the load*.d
|
/* This is a file that imports common modules used by the load*.d
|
||||||
record loaders. It is really a cut down version of the start of
|
record loaders. It is really a cut down version of what used to be
|
||||||
records.d.
|
the start of records.d.
|
||||||
|
|
||||||
This file MUST NOT import records.d - directly or indirectly -
|
This file MUST NOT import records.d - directly or indirectly -
|
||||||
because that will trigger a nice three page long list of template
|
because that will trigger a nice three page long list of template
|
||||||
|
@ -41,4 +41,7 @@ import esm.loadscpt;
|
||||||
import esm.loadsoun;
|
import esm.loadsoun;
|
||||||
import esm.loadspel;
|
import esm.loadspel;
|
||||||
import esm.loadench;
|
import esm.loadench;
|
||||||
|
|
||||||
|
import monster.monster;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,10 +36,8 @@ import esm.imports;
|
||||||
|
|
||||||
struct Activator
|
struct Activator
|
||||||
{
|
{
|
||||||
char[] id;
|
mixin LoadT!();
|
||||||
LoadState state;
|
|
||||||
|
|
||||||
char[] name;
|
|
||||||
Script *script;
|
Script *script;
|
||||||
MeshIndex model;
|
MeshIndex model;
|
||||||
|
|
||||||
|
@ -48,6 +46,8 @@ struct Activator
|
||||||
model = getMesh();
|
model = getMesh();
|
||||||
name = getHNString("FNAM");
|
name = getHNString("FNAM");
|
||||||
script = getHNOPtr!(Script)("SCRI", scripts);
|
script = getHNOPtr!(Script)("SCRI", scripts);
|
||||||
|
|
||||||
|
makeProto();
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ListID!(Activator) activators;
|
ListID!(Activator) activators;
|
||||||
|
|
|
@ -30,9 +30,6 @@ import esm.imports;
|
||||||
|
|
||||||
struct Potion
|
struct Potion
|
||||||
{
|
{
|
||||||
char[] id;
|
|
||||||
LoadState state;
|
|
||||||
|
|
||||||
align(1) struct ALDTstruct
|
align(1) struct ALDTstruct
|
||||||
{
|
{
|
||||||
float weight;
|
float weight;
|
||||||
|
@ -43,7 +40,7 @@ struct Potion
|
||||||
|
|
||||||
ALDTstruct data;
|
ALDTstruct data;
|
||||||
|
|
||||||
char[] name;
|
mixin LoadT!();
|
||||||
|
|
||||||
MeshIndex model;
|
MeshIndex model;
|
||||||
IconIndex icon;
|
IconIndex icon;
|
||||||
|
@ -69,6 +66,8 @@ struct Potion
|
||||||
readHExact(&effects.array[$-1], effects.array[$-1].sizeof);
|
readHExact(&effects.array[$-1], effects.array[$-1].sizeof);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
makeProto();
|
||||||
|
proto.setInt("autoCalc", data.autoCalc);
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ListID!(Potion) potions;
|
ListID!(Potion) potions;
|
||||||
|
|
|
@ -30,9 +30,6 @@ import esm.imports;
|
||||||
|
|
||||||
struct Apparatus
|
struct Apparatus
|
||||||
{
|
{
|
||||||
char[] id, name;
|
|
||||||
LoadState state;
|
|
||||||
|
|
||||||
enum AppaType : int
|
enum AppaType : int
|
||||||
{
|
{
|
||||||
MortarPestle = 0,
|
MortarPestle = 0,
|
||||||
|
@ -50,6 +47,8 @@ struct Apparatus
|
||||||
|
|
||||||
static assert(AADTstruct.sizeof == 16);
|
static assert(AADTstruct.sizeof == 16);
|
||||||
}
|
}
|
||||||
|
mixin LoadT!();
|
||||||
|
|
||||||
AADTstruct data;
|
AADTstruct data;
|
||||||
MeshIndex model;
|
MeshIndex model;
|
||||||
IconIndex icon;
|
IconIndex icon;
|
||||||
|
@ -62,6 +61,11 @@ struct Apparatus
|
||||||
readHNExact(&data, data.sizeof, "AADT");
|
readHNExact(&data, data.sizeof, "AADT");
|
||||||
script = getHNOPtr!(Script)("SCRI", scripts);
|
script = getHNOPtr!(Script)("SCRI", scripts);
|
||||||
icon = getIcon();
|
icon = getIcon();
|
||||||
|
|
||||||
|
makeProto();
|
||||||
|
|
||||||
|
proto.setFloat("quality", data.quality);
|
||||||
|
proto.setInt("type", data.type);
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ListID!(Apparatus) appas;
|
ListID!(Apparatus) appas;
|
||||||
|
|
|
@ -116,8 +116,7 @@ struct Armor
|
||||||
|
|
||||||
AODTstruct data;
|
AODTstruct data;
|
||||||
|
|
||||||
char[] name, id;
|
mixin LoadT!();
|
||||||
LoadState state;
|
|
||||||
|
|
||||||
PartReferenceList parts;
|
PartReferenceList parts;
|
||||||
|
|
||||||
|
@ -138,6 +137,11 @@ struct Armor
|
||||||
parts.load();
|
parts.load();
|
||||||
|
|
||||||
enchant = getHNOPtr!(Enchantment)("ENAM", enchants);
|
enchant = getHNOPtr!(Enchantment)("ENAM", enchants);
|
||||||
|
|
||||||
|
makeProto();
|
||||||
|
|
||||||
|
proto.setInt("type", data.type);
|
||||||
|
proto.setInt("armor", data.armor);
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ListID!(Armor) armors;
|
ListID!(Armor) armors;
|
||||||
|
|
|
@ -74,8 +74,8 @@ struct BodyPart
|
||||||
|
|
||||||
BYDTstruct data;
|
BYDTstruct data;
|
||||||
|
|
||||||
char[] name, id;
|
mixin LoadT;
|
||||||
LoadState state;
|
|
||||||
MeshIndex model;
|
MeshIndex model;
|
||||||
|
|
||||||
void load()
|
void load()
|
||||||
|
@ -83,6 +83,9 @@ struct BodyPart
|
||||||
model = getMesh();
|
model = getMesh();
|
||||||
name = getHNString("FNAM");
|
name = getHNString("FNAM");
|
||||||
readHNExact(&data, data.sizeof, "BYDT");
|
readHNExact(&data, data.sizeof, "BYDT");
|
||||||
|
|
||||||
|
// don't need to run makeProto here yet, no BodyPart monster
|
||||||
|
// class.
|
||||||
}}
|
}}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,9 @@ struct Book
|
||||||
IconIndex icon;
|
IconIndex icon;
|
||||||
Script *script;
|
Script *script;
|
||||||
Enchantment *enchant;
|
Enchantment *enchant;
|
||||||
char[] name, text, id;
|
|
||||||
|
mixin LoadT;
|
||||||
|
char[] text;
|
||||||
|
|
||||||
LoadState state;
|
LoadState state;
|
||||||
|
|
||||||
|
@ -57,6 +59,11 @@ struct Book
|
||||||
icon = getIcon();
|
icon = getIcon();
|
||||||
text = getHNOString("TEXT");
|
text = getHNOString("TEXT");
|
||||||
enchant = getHNOPtr!(Enchantment)("ENAM", enchants);
|
enchant = getHNOPtr!(Enchantment)("ENAM", enchants);
|
||||||
|
|
||||||
|
makeProto();
|
||||||
|
|
||||||
|
proto.setInt("skillID", data.skillID);
|
||||||
|
proto.setBool("isScroll", data.isScroll != 0);
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ListID!(Book) books;
|
ListID!(Book) books;
|
||||||
|
|
|
@ -30,9 +30,9 @@ import esm.imports;
|
||||||
|
|
||||||
struct BirthSign
|
struct BirthSign
|
||||||
{
|
{
|
||||||
LoadState state;
|
char[] description;
|
||||||
|
|
||||||
char[] id, name, description;
|
mixin LoadT;
|
||||||
|
|
||||||
TextureIndex texture;
|
TextureIndex texture;
|
||||||
|
|
||||||
|
@ -48,6 +48,8 @@ struct BirthSign
|
||||||
description = getHNOString("DESC");
|
description = getHNOString("DESC");
|
||||||
|
|
||||||
powers.load();
|
powers.load();
|
||||||
|
|
||||||
|
// No monster class equivalent yet
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ListID!(BirthSign) birthSigns;
|
ListID!(BirthSign) birthSigns;
|
||||||
|
|
|
@ -72,8 +72,9 @@ struct Class
|
||||||
static assert(CLDTstruct.sizeof == 60);
|
static assert(CLDTstruct.sizeof == 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadState state;
|
mixin LoadT;
|
||||||
char[] id, name, description;
|
|
||||||
|
char[] description;
|
||||||
CLDTstruct data;
|
CLDTstruct data;
|
||||||
|
|
||||||
void load()
|
void load()
|
||||||
|
@ -85,6 +86,8 @@ struct Class
|
||||||
esFile.fail("Unknown bool value");
|
esFile.fail("Unknown bool value");
|
||||||
|
|
||||||
description = esFile.getHNOString("DESC");
|
description = esFile.getHNOString("DESC");
|
||||||
|
|
||||||
|
// no makeProto yet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ListID!(Class) classes;
|
ListID!(Class) classes;
|
||||||
|
|
|
@ -50,15 +50,15 @@ struct Clothing
|
||||||
Type type;
|
Type type;
|
||||||
float weight;
|
float weight;
|
||||||
short value;
|
short value;
|
||||||
short enchantPoints;
|
short enchant;
|
||||||
|
|
||||||
static assert(CTDTstruct.sizeof == 12);
|
static assert(CTDTstruct.sizeof == 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
CTDTstruct data;
|
CTDTstruct data;
|
||||||
|
|
||||||
LoadState state;
|
mixin LoadT;
|
||||||
char[] id, name;
|
|
||||||
PartReferenceList parts;
|
PartReferenceList parts;
|
||||||
|
|
||||||
MeshIndex model;
|
MeshIndex model;
|
||||||
|
@ -78,6 +78,9 @@ struct Clothing
|
||||||
parts.load();
|
parts.load();
|
||||||
|
|
||||||
enchant = getHNOPtr!(Enchantment)("ENAM", enchants);
|
enchant = getHNOPtr!(Enchantment)("ENAM", enchants);
|
||||||
|
|
||||||
|
makeProto();
|
||||||
|
proto.setInt("type", data.type);
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ListID!(Clothing) clothes;
|
ListID!(Clothing) clothes;
|
||||||
|
|
|
@ -69,9 +69,6 @@ struct Container
|
||||||
Unknown = 8
|
Unknown = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
char[] id, name;
|
|
||||||
LoadState state;
|
|
||||||
|
|
||||||
MeshIndex model;
|
MeshIndex model;
|
||||||
Script *script;
|
Script *script;
|
||||||
|
|
||||||
|
@ -79,6 +76,8 @@ struct Container
|
||||||
Flags flags;
|
Flags flags;
|
||||||
InventoryList inventory;
|
InventoryList inventory;
|
||||||
|
|
||||||
|
mixin LoadT!();
|
||||||
|
|
||||||
void load()
|
void load()
|
||||||
{with(esFile){
|
{with(esFile){
|
||||||
model = getMesh();
|
model = getMesh();
|
||||||
|
@ -100,6 +99,9 @@ struct Container
|
||||||
script = getHNOPtr!(Script)("SCRI", scripts);
|
script = getHNOPtr!(Script)("SCRI", scripts);
|
||||||
|
|
||||||
inventory.load();
|
inventory.load();
|
||||||
|
|
||||||
|
makeProto();
|
||||||
|
proto.setFloat("weight", weight);
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,13 +30,12 @@ import esm.imports;
|
||||||
|
|
||||||
struct Door
|
struct Door
|
||||||
{
|
{
|
||||||
LoadState state;
|
|
||||||
char[] id, name;
|
|
||||||
|
|
||||||
MeshIndex model;
|
MeshIndex model;
|
||||||
Script *script;
|
Script *script;
|
||||||
Sound* openSound, closeSound;
|
Sound* openSound, closeSound;
|
||||||
|
|
||||||
|
mixin LoadT!();
|
||||||
|
|
||||||
void load()
|
void load()
|
||||||
{with(esFile){
|
{with(esFile){
|
||||||
model = getMesh();
|
model = getMesh();
|
||||||
|
@ -44,6 +43,8 @@ struct Door
|
||||||
script = getHNOPtr!(Script)("SCRI", scripts);
|
script = getHNOPtr!(Script)("SCRI", scripts);
|
||||||
openSound = getHNOPtr!(Sound)("SNAM", sounds);
|
openSound = getHNOPtr!(Sound)("SNAM", sounds);
|
||||||
closeSound = getHNOPtr!(Sound)("ANAM", sounds);
|
closeSound = getHNOPtr!(Sound)("ANAM", sounds);
|
||||||
|
|
||||||
|
makeProto();
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ListID!(Door) doors; // Break on through
|
ListID!(Door) doors; // Break on through
|
||||||
|
|
|
@ -29,9 +29,6 @@ import esm.imports;
|
||||||
|
|
||||||
struct Light
|
struct Light
|
||||||
{
|
{
|
||||||
char[] id;
|
|
||||||
LoadState state;
|
|
||||||
|
|
||||||
enum Flags : uint
|
enum Flags : uint
|
||||||
{
|
{
|
||||||
Dynamic = 0x001,
|
Dynamic = 0x001,
|
||||||
|
@ -59,14 +56,14 @@ struct Light
|
||||||
|
|
||||||
LHDTstruct data;
|
LHDTstruct data;
|
||||||
|
|
||||||
char[] name;
|
mixin LoadT!();
|
||||||
|
|
||||||
MeshIndex model;
|
|
||||||
IconIndex icon;
|
|
||||||
|
|
||||||
Sound* sound;
|
Sound* sound;
|
||||||
Script* script;
|
Script* script;
|
||||||
|
|
||||||
|
MeshIndex model;
|
||||||
|
IconIndex icon;
|
||||||
|
|
||||||
void load()
|
void load()
|
||||||
{with(esFile){
|
{with(esFile){
|
||||||
model = getMesh();
|
model = getMesh();
|
||||||
|
@ -77,6 +74,14 @@ struct Light
|
||||||
|
|
||||||
script = getHNOPtr!(Script)("SCRI", scripts);
|
script = getHNOPtr!(Script)("SCRI", scripts);
|
||||||
sound = getHNOPtr!(Sound)("SNAM", sounds);
|
sound = getHNOPtr!(Sound)("SNAM", sounds);
|
||||||
|
|
||||||
|
// Stash the data in the Monster object prototype
|
||||||
|
|
||||||
|
makeProto();
|
||||||
|
|
||||||
|
proto.setUint("flags", data.flags);
|
||||||
|
proto.setFloat("lifetime", data.time);
|
||||||
|
proto.setInt("radius", data.radius);
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ListID!(Light) lights;
|
ListID!(Light) lights;
|
||||||
|
|
|
@ -71,8 +71,7 @@ struct Weapon
|
||||||
|
|
||||||
WPDTstruct data;
|
WPDTstruct data;
|
||||||
|
|
||||||
LoadState state;
|
mixin LoadT!();
|
||||||
char[] name, id;
|
|
||||||
|
|
||||||
MeshIndex model;
|
MeshIndex model;
|
||||||
IconIndex icon;
|
IconIndex icon;
|
||||||
|
@ -87,6 +86,11 @@ struct Weapon
|
||||||
script = getHNOPtr!(Script)("SCRI", scripts);
|
script = getHNOPtr!(Script)("SCRI", scripts);
|
||||||
icon = getOIcon();
|
icon = getOIcon();
|
||||||
enchant = getHNOPtr!(Enchantment)("ENAM", enchants);
|
enchant = getHNOPtr!(Enchantment)("ENAM", enchants);
|
||||||
|
|
||||||
|
makeProto();
|
||||||
|
|
||||||
|
proto.setFloat("speed", data.speed);
|
||||||
|
proto.setFloat("reach", data.reach);
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ListID!(Weapon) weapons;
|
ListID!(Weapon) weapons;
|
||||||
|
|
|
@ -393,6 +393,8 @@ struct Assembler
|
||||||
addi(i);
|
addi(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cloneObj() { cmd(BC.Clone); }
|
||||||
|
|
||||||
// Copy the topmost int on the stack
|
// Copy the topmost int on the stack
|
||||||
void dup() { cmd(BC.Dup); }
|
void dup() { cmd(BC.Dup); }
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,12 @@ enum BC
|
||||||
// giving the class index (in the file lookup
|
// giving the class index (in the file lookup
|
||||||
// table)
|
// table)
|
||||||
|
|
||||||
|
Clone, // Clones an object - create a new object of
|
||||||
|
// the same class, then copy variable values
|
||||||
|
// and state from the old object to the
|
||||||
|
// new. Replaces the object index on the stack
|
||||||
|
// with the new index.
|
||||||
|
|
||||||
Jump, // Jump to given position (int)
|
Jump, // Jump to given position (int)
|
||||||
|
|
||||||
JumpZ, // Pop a value, if it is zero then jump to
|
JumpZ, // Pop a value, if it is zero then jump to
|
||||||
|
|
|
@ -1004,6 +1004,7 @@ class VariableExpr : MemberExpression
|
||||||
isNext(toks, TT.Identifier) ||
|
isNext(toks, TT.Identifier) ||
|
||||||
isNext(toks, TT.Singleton) ||
|
isNext(toks, TT.Singleton) ||
|
||||||
isNext(toks, TT.State) ||
|
isNext(toks, TT.State) ||
|
||||||
|
isNext(toks, TT.Clone) ||
|
||||||
isNext(toks, TT.Const);
|
isNext(toks, TT.Const);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1146,6 +1147,9 @@ class VariableExpr : MemberExpression
|
||||||
if(name.type == TT.Const)
|
if(name.type == TT.Const)
|
||||||
fail("Cannot use const as a variable", name.loc);
|
fail("Cannot use const as a variable", name.loc);
|
||||||
|
|
||||||
|
if(name.type == TT.Clone)
|
||||||
|
fail("Cannot use clone as a variable", name.loc);
|
||||||
|
|
||||||
// These are special cases that work both as properties
|
// These are special cases that work both as properties
|
||||||
// (object.state) and as non-member variables (state=...) inside
|
// (object.state) and as non-member variables (state=...) inside
|
||||||
// class functions / state code. Since we already handle them
|
// class functions / state code. Since we already handle them
|
||||||
|
|
|
@ -159,6 +159,8 @@ class ClassProperties : SimplePropertyScope
|
||||||
{
|
{
|
||||||
super("ClassProperties");
|
super("ClassProperties");
|
||||||
|
|
||||||
|
insert("clone", "owner", { tasm.cloneObj(); });
|
||||||
|
|
||||||
// For testing purposes. Makes 'singleton' an alias for the
|
// For testing purposes. Makes 'singleton' an alias for the
|
||||||
// first variable in the data segment. This might actually not
|
// first variable in the data segment. This might actually not
|
||||||
// be far from how the end result would work - the singleton
|
// be far from how the end result would work - the singleton
|
||||||
|
|
|
@ -537,6 +537,41 @@ final class MonsterClass
|
||||||
return top;
|
return top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new object based on an existing object
|
||||||
|
MonsterObject* createClone(MonsterObject *source)
|
||||||
|
{
|
||||||
|
requireCompile();
|
||||||
|
|
||||||
|
assert(source.tree.length == tree.length);
|
||||||
|
assert(source.thread.topObj == source,
|
||||||
|
"createClone can only clone the topmost object");
|
||||||
|
|
||||||
|
// Create a new thread
|
||||||
|
CodeThread *trd = threads.getNew();
|
||||||
|
|
||||||
|
// Loop through the objects in the source tree, and clone each
|
||||||
|
// of them
|
||||||
|
MonsterObject* otree[] = source.tree.dup;
|
||||||
|
foreach(i, ref obj; otree)
|
||||||
|
{
|
||||||
|
obj = obj.cls.getClone(obj);
|
||||||
|
obj.tree = otree[0..i+1];
|
||||||
|
obj.thread = trd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick out the top object
|
||||||
|
MonsterObject* top = otree[$-1];
|
||||||
|
assert(top !is null);
|
||||||
|
|
||||||
|
// Initialize the thread
|
||||||
|
trd.initialize(top);
|
||||||
|
|
||||||
|
// Set the same state
|
||||||
|
trd.setState(source.thread.getState(), null);
|
||||||
|
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
// Free an object and its thread
|
// Free an object and its thread
|
||||||
void deleteObject(MonsterObject *obj)
|
void deleteObject(MonsterObject *obj)
|
||||||
{
|
{
|
||||||
|
@ -757,6 +792,46 @@ final class MonsterClass
|
||||||
|
|
||||||
// Point to the static data segment
|
// Point to the static data segment
|
||||||
obj.sdata = sdata;
|
obj.sdata = sdata;
|
||||||
|
obj.extra = null;
|
||||||
|
|
||||||
|
// Call the custom native constructor
|
||||||
|
if(constType != FuncType.Native)
|
||||||
|
{
|
||||||
|
fstack.pushNConst(obj);
|
||||||
|
if(constType == FuncType.NativeDDel)
|
||||||
|
dg_const();
|
||||||
|
else if(constType == FuncType.NativeDFunc)
|
||||||
|
fn_const();
|
||||||
|
else if(constType == FuncType.NativeCFunc)
|
||||||
|
c_const();
|
||||||
|
fstack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone an existing object
|
||||||
|
MonsterObject *getClone(MonsterObject *source)
|
||||||
|
{
|
||||||
|
assert(source !is null);
|
||||||
|
assert(source.cls is this);
|
||||||
|
assert(source.data.length == data.length);
|
||||||
|
assert(source.sdata.ptr is sdata.ptr);
|
||||||
|
|
||||||
|
requireCompile();
|
||||||
|
|
||||||
|
MonsterObject *obj = objects.getNew();
|
||||||
|
|
||||||
|
// Set the class
|
||||||
|
obj.cls = this;
|
||||||
|
|
||||||
|
// TODO: Fix memory management here too.
|
||||||
|
// Copy the data segment from the source
|
||||||
|
obj.data = source.data.dup;
|
||||||
|
|
||||||
|
// Point to the static data segment
|
||||||
|
obj.sdata = sdata;
|
||||||
|
obj.extra = null;
|
||||||
|
|
||||||
// Call the custom native constructor
|
// Call the custom native constructor
|
||||||
if(constType != FuncType.Native)
|
if(constType != FuncType.Native)
|
||||||
|
|
|
@ -69,6 +69,7 @@ struct MonsterObject
|
||||||
// the MonsterClass.
|
// the MonsterClass.
|
||||||
MonsterObject* tree[];
|
MonsterObject* tree[];
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************
|
/*******************************************************
|
||||||
* *
|
* *
|
||||||
* Functions for object handling *
|
* Functions for object handling *
|
||||||
|
@ -98,6 +99,16 @@ struct MonsterObject
|
||||||
cls.deleteObject(this);
|
cls.deleteObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a clone of this object. Note that this will always clone
|
||||||
|
// and return the top object (thread.topObj), regardless of which
|
||||||
|
// object in the list it is called on. In other words, the class
|
||||||
|
// mo.cls is not always the same as mo.clone().cls.
|
||||||
|
MonsterObject *clone()
|
||||||
|
{
|
||||||
|
auto t = thread.topObj;
|
||||||
|
return t.cls.createClone(t);
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************
|
/*******************************************************
|
||||||
* *
|
* *
|
||||||
* Casting / polymorphism functions *
|
* Casting / polymorphism functions *
|
||||||
|
|
|
@ -480,6 +480,10 @@ struct CodeThread
|
||||||
.createObject());
|
.createObject());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BC.Clone:
|
||||||
|
stack.pushObject(stack.popObject().clone());
|
||||||
|
break;
|
||||||
|
|
||||||
case BC.Jump:
|
case BC.Jump:
|
||||||
code.jump(code.getInt);
|
code.jump(code.getInt);
|
||||||
break;
|
break;
|
||||||
|
|
25
mscripts/gameobjects/activator.mn
Normal file
25
mscripts/gameobjects/activator.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 (activator.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 Activator : GameObject;
|
||||||
|
|
28
mscripts/gameobjects/apparatus.mn
Normal file
28
mscripts/gameobjects/apparatus.mn
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
OpenMW - The completely unofficial reimplementation of Morrowind
|
||||||
|
Copyright (C) 2008 Nicolay Korslund
|
||||||
|
Email: < korslund@gmail.com >
|
||||||
|
WWW: http://openmw.snaptoad.com/
|
||||||
|
|
||||||
|
This file (apparatus.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/ .
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Covers all alchemy apparatus - mortars, retorts, etc
|
||||||
|
class Apparatus : InventoryItem;
|
||||||
|
|
||||||
|
float quality;
|
||||||
|
int type;
|
28
mscripts/gameobjects/armor.mn
Normal file
28
mscripts/gameobjects/armor.mn
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
OpenMW - The completely unofficial reimplementation of Morrowind
|
||||||
|
Copyright (C) 2008 Nicolay Korslund
|
||||||
|
Email: < korslund@gmail.com >
|
||||||
|
WWW: http://openmw.snaptoad.com/
|
||||||
|
|
||||||
|
This file (armor.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/ .
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Covers all weapons and projectile weapons you can carry (like
|
||||||
|
// arrows and throwable items.)
|
||||||
|
class Armor : Repairable;
|
||||||
|
|
||||||
|
int type, armor;
|
28
mscripts/gameobjects/book.mn
Normal file
28
mscripts/gameobjects/book.mn
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
OpenMW - The completely unofficial reimplementation of Morrowind
|
||||||
|
Copyright (C) 2008 Nicolay Korslund
|
||||||
|
Email: < korslund@gmail.com >
|
||||||
|
WWW: http://openmw.snaptoad.com/
|
||||||
|
|
||||||
|
This file (book.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 Book : EnchantItem;
|
||||||
|
|
||||||
|
bool isScroll;
|
||||||
|
|
||||||
|
int skillID; // Skill that is enhanced by reading this book, if any
|
27
mscripts/gameobjects/clothing.mn
Normal file
27
mscripts/gameobjects/clothing.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 (clothing.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/ .
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// All items that can be repaired (weapons and armor)
|
||||||
|
class Clothing : EnchantItem;
|
||||||
|
|
||||||
|
int type;
|
26
mscripts/gameobjects/container.mn
Normal file
26
mscripts/gameobjects/container.mn
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
OpenMW - The completely unofficial reimplementation of Morrowind
|
||||||
|
Copyright (C) 2008 Nicolay Korslund
|
||||||
|
Email: < korslund@gmail.com >
|
||||||
|
WWW: http://openmw.snaptoad.com/
|
||||||
|
|
||||||
|
This file (container.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 Container : LockedObject;
|
||||||
|
|
||||||
|
float weight; // Not sure, might be max total weight allowed?
|
|
@ -4,7 +4,7 @@
|
||||||
Email: < korslund@gmail.com >
|
Email: < korslund@gmail.com >
|
||||||
WWW: http://openmw.snaptoad.com/
|
WWW: http://openmw.snaptoad.com/
|
||||||
|
|
||||||
This file (equipitem.mn) is part of the OpenMW package.
|
This file (enchantitem.mn) is part of the OpenMW package.
|
||||||
|
|
||||||
OpenMW is distributed as free software: you can redistribute it
|
OpenMW is distributed as free software: you can redistribute it
|
||||||
and/or modify it under the terms of the GNU General Public License
|
and/or modify it under the terms of the GNU General Public License
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Anything that can be equiped, like clothes, armor and weapons.
|
// Items that can be enchanted
|
||||||
class EquipItem : InventoryItem;
|
class EnchantItem : InventoryItem;
|
||||||
|
|
||||||
int enchant;
|
int enchant;
|
|
@ -40,6 +40,8 @@ float r1, r2, r3;
|
||||||
|
|
||||||
float scale;
|
float scale;
|
||||||
|
|
||||||
|
char[] name, id;
|
||||||
|
|
||||||
// Various variables that are currently unused. Most of the strings
|
// Various variables that are currently unused. Most of the strings
|
||||||
// will be replaced by object references at some point.
|
// will be replaced by object references at some point.
|
||||||
|
|
||||||
|
|
|
@ -26,5 +26,6 @@ class Light : InventoryItem;
|
||||||
// Time left in seconds (for carried lights)
|
// Time left in seconds (for carried lights)
|
||||||
float lifetime;
|
float lifetime;
|
||||||
|
|
||||||
// Is this a carryable light?
|
int radius;
|
||||||
bool carry;
|
uint flags;
|
||||||
|
|
||||||
|
|
26
mscripts/gameobjects/potion.mn
Normal file
26
mscripts/gameobjects/potion.mn
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
OpenMW - The completely unofficial reimplementation of Morrowind
|
||||||
|
Copyright (C) 2008 Nicolay Korslund
|
||||||
|
Email: < korslund@gmail.com >
|
||||||
|
WWW: http://openmw.snaptoad.com/
|
||||||
|
|
||||||
|
This file (potion.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 Potion : InventoryItem;
|
||||||
|
|
||||||
|
int autoCalc;
|
27
mscripts/gameobjects/repairable.mn
Normal file
27
mscripts/gameobjects/repairable.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 (repairable.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/ .
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// All items that can be repaired (weapons and armor)
|
||||||
|
class Repairable : EnchantItem;
|
||||||
|
|
||||||
|
int health;
|
|
@ -21,11 +21,11 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Weapons (This is just an example, it's not used for anything yet.)
|
// Covers all weapons and carry-able projectiles.
|
||||||
class Weapon : EquipItem;
|
class Weapon : Repairable;
|
||||||
|
|
||||||
float speed, reach;
|
float speed, reach;
|
||||||
|
|
||||||
|
// Not set yet.
|
||||||
bool magical, silver;
|
bool magical, silver;
|
||||||
bool isTwohanded;
|
bool twoHanded;
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,8 @@ import sound.audio;
|
||||||
|
|
||||||
import scene.player;
|
import scene.player;
|
||||||
|
|
||||||
// Generic version of a "live" object
|
// Generic version of a "live" object. Do we even need this at all?
|
||||||
|
// No, I don't think so.
|
||||||
struct GenLive(T)
|
struct GenLive(T)
|
||||||
{
|
{
|
||||||
// Instance of class GameObject or a derived class (depending on
|
// Instance of class GameObject or a derived class (depending on
|
||||||
|
@ -259,16 +260,13 @@ class CellData
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static
|
static
|
||||||
MonsterClass gameObjC, doorC, lightC, lockedC;
|
MonsterClass gameObjC;
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
if(gameObjC !is null) return;
|
if(gameObjC !is null) return;
|
||||||
|
|
||||||
gameObjC = new MonsterClass("GameObject");
|
gameObjC = MonsterClass.find("GameObject");
|
||||||
doorC = new MonsterClass("Door");
|
|
||||||
lightC = new MonsterClass("Light");
|
|
||||||
lockedC = new MonsterClass("LockedObject");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadReferences()
|
void loadReferences()
|
||||||
|
@ -329,24 +327,20 @@ class CellData
|
||||||
{
|
{
|
||||||
LiveLight ls;
|
LiveLight ls;
|
||||||
ls.m = m;
|
ls.m = m;
|
||||||
ls.obj = lightC.createObject;
|
ls.obj = m.proto.clone();
|
||||||
mo = ls.obj;
|
mo = ls.obj;
|
||||||
|
|
||||||
mo.setFloat("lifetime", m.data.time);
|
|
||||||
bool carry = (m.data.flags&Light.Flags.Carry) != 0;
|
bool carry = (m.data.flags&Light.Flags.Carry) != 0;
|
||||||
mo.setBool("carry", carry);
|
|
||||||
|
|
||||||
if(carry)
|
if(carry)
|
||||||
lights.insert(ls);
|
lights.insert(ls);
|
||||||
else
|
else
|
||||||
statLights.insert(ls);
|
statLights.insert(ls);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(Container *c = it.getContainer())
|
else if(Container *c = it.getContainer())
|
||||||
{
|
{
|
||||||
LiveContainer ls;
|
LiveContainer ls;
|
||||||
ls.m = c;
|
ls.m = c;
|
||||||
ls.obj = lockedC.createObject;
|
ls.obj = c.proto.clone();
|
||||||
mo = ls.obj;
|
mo = ls.obj;
|
||||||
containers.insert(ls);
|
containers.insert(ls);
|
||||||
container = true;
|
container = true;
|
||||||
|
@ -356,7 +350,7 @@ class CellData
|
||||||
{
|
{
|
||||||
LiveDoor ls;
|
LiveDoor ls;
|
||||||
ls.m = d;
|
ls.m = d;
|
||||||
ls.obj = doorC.createObject;
|
ls.obj = d.proto.clone();
|
||||||
mo = ls.obj;
|
mo = ls.obj;
|
||||||
doors.insert(ls);
|
doors.insert(ls);
|
||||||
door = true;
|
door = true;
|
||||||
|
@ -416,7 +410,7 @@ class CellData
|
||||||
{
|
{
|
||||||
LiveWeapon ls;
|
LiveWeapon ls;
|
||||||
ls.m = m;
|
ls.m = m;
|
||||||
ls.obj = gameObjC.createObject;
|
ls.obj = m.proto.clone();
|
||||||
mo = ls.obj;
|
mo = ls.obj;
|
||||||
weapons.insert(ls);
|
weapons.insert(ls);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue