frame timers: completely rewritten
[dd2d.git] / d2dadefs.d
blob49d384b8a0f67f2daa3959c00606751195f6c977
1 module d2dadefs is aliced;
3 private:
4 import glutils;
5 import console;
6 import dacs;
7 import d2dgfx;
10 // ////////////////////////////////////////////////////////////////////////// //
11 // known D2D actors (and pseudoactors)
12 struct ActorDefD2D {
13 string classtype;
14 string classname;
15 string fullname;
16 ushort mapid; // thing id in map
18 this (string ctype, string cname, ushort thid) { classtype = ctype; classname = cname; fullname = classtype~":"~classname; mapid = thid; }
20 string toString () const {
21 import std.string : format;
22 return "ActorDefD2D(%s, %s, %s)".format(classtype/*.quote*/, classname/*.quote*/, mapid);
26 immutable ActorDefD2D[$] d2dactordefs = [
27 ActorDefD2D("playerstart", "Player1", 1),
28 ActorDefD2D("playerstart", "Player2", 2),
29 ActorDefD2D("playerstart", "DMStart", 3),
30 ActorDefD2D("item", "Clip", 100),
31 ActorDefD2D("item", "Shell", 101),
32 ActorDefD2D("item", "Rocket", 102),
33 ActorDefD2D("item", "Cell", 103),
34 ActorDefD2D("item", "Ammo", 104),
35 ActorDefD2D("item", "ShellBox", 105),
36 ActorDefD2D("item", "RocketBox", 106),
37 ActorDefD2D("item", "CellPack", 107),
38 ActorDefD2D("item", "StimPack", 108),
39 ActorDefD2D("item", "MediKit", 109),
40 ActorDefD2D("item", "BackPack", 110),
41 ActorDefD2D("item", "Chainsaw", 111),
42 ActorDefD2D("item", "Shotgun", 112),
43 ActorDefD2D("item", "SuperShotgun", 113),
44 ActorDefD2D("item", "MachineGun", 114),
45 ActorDefD2D("item", "RocketLauncher", 115),
46 ActorDefD2D("item", "Plasmagun", 116),
47 ActorDefD2D("item", "BFG900", 117),
48 ActorDefD2D("item", "Armor1", 118),
49 ActorDefD2D("item", "Armor2", 119),
50 ActorDefD2D("item", "MegaSphere", 120),
51 ActorDefD2D("item", "Invulnerability", 121),
52 ActorDefD2D("item", "Aqualung", 122),
53 ActorDefD2D("item", "RedKey", 123),
54 ActorDefD2D("item", "GreenKey", 124),
55 ActorDefD2D("item", "BlueKey", 125),
56 ActorDefD2D("item", "ProtectionSuit", 126),
57 ActorDefD2D("item", "Super", 127),
58 ActorDefD2D("item", "RedTorch", 128),
59 ActorDefD2D("item", "GreenTorch", 129),
60 ActorDefD2D("item", "BlueTorch", 130),
61 ActorDefD2D("item", "Gor1", 131),
62 ActorDefD2D("item", "FCan", 132),
63 ActorDefD2D("item", "Gun2", 133),
64 ActorDefD2D("monster", "Demon", 200),
65 ActorDefD2D("monster", "Imp", 201),
66 ActorDefD2D("monster", "Zombie", 202),
67 ActorDefD2D("monster", "Sergeant", 203),
68 ActorDefD2D("monster", "Cyberdemon", 204),
69 ActorDefD2D("monster", "Chaingunner", 205),
70 ActorDefD2D("monster", "BaronOfHell", 206),
71 ActorDefD2D("monster", "HellKnight", 207),
72 ActorDefD2D("monster", "Cacodemon", 208),
73 ActorDefD2D("monster", "LostSoul", 209),
74 ActorDefD2D("monster", "PainElemental", 210),
75 ActorDefD2D("monster", "SpiderMastermind", 211),
76 ActorDefD2D("monster", "Arachnotron", 212),
77 ActorDefD2D("monster", "Mancubus", 213),
78 ActorDefD2D("monster", "Revenant", 214),
79 ActorDefD2D("monster", "Archvile", 215),
80 ActorDefD2D("monster", "Fish", 216),
81 ActorDefD2D("monster", "Barrel", 217),
82 ActorDefD2D("monster", "Robot", 218),
83 ActorDefD2D("monster", "Man", 219),
87 public immutable ActorDefD2D[ushort] d2dactordefsById;
88 //immutable ActorDefD2D[string] d2dactordefsByTN; // by "type:name"
90 shared static this () {
91 foreach (const ref ActorDefD2D d2da; d2dactordefs) {
92 d2dactordefsById[d2da.mapid] = d2da;
93 //d2dactordefsByTN[d2da.fullname] = d2da;
98 // ////////////////////////////////////////////////////////////////////////// //
99 public struct ImgSprite {
100 D2DImage vga;
101 Texture tex;
102 bool mirrored;
104 @disable this (this);
108 public final class ActorDef {
109 string classtype;
110 string classname;
111 string fullname;
112 uint id; // actor's unique id
114 // animation sequences for stated; keyed by state strid
115 StrId[][][uint] anims; // [statestrid][dir][pos]
117 FuncPool.FuncInfo[] fiAnimInit;
118 FuncPool.FuncInfo fiInit;
119 FuncPool.FuncInfo fiThink;
121 __gshared ImgSprite[uint] allSprites; // to avoid loading sprites twice they are keyed by namestrid
122 ImgSprite*[][][uint] animSprites;
123 //__gshared ImgSprite*[][] animCur;
125 // load actor graphics
126 void loadGraphics () {
127 //conwriteln("loading graphics for '", fullname, "'; anims.length=", anims.length, "; allSprites.length=", allSprites.length);
128 if (anims.length == 0) return; // no graphics here
129 //if (allSprites.length > 0) return;
130 // load sprites
131 foreach (auto anma2; anims.byValue) {
132 foreach (auto anma; anma2) {
133 foreach (StrId ssid; anma) {
134 //conwriteln(fullname, ": ssid=", ssid.id, "; is ", ssid.get);
135 ImgSprite* spi = null;
136 if (ssid.id != 0) {
137 spi = ssid.id in allSprites;
138 if (spi is null) {
139 //conwriteln("loading sprite '", ssid.get, "'");
140 D2DImage vga = new D2DImage(ssid.get);
141 allSprites[ssid.id] = ImgSprite();
142 spi = ssid.id in allSprites;
143 assert(spi !is null);
144 spi.vga = vga;
145 spi.tex = new Texture(spi.vga.asTCImage, Texture.Option.Nearest);
146 } else {
147 //conwriteln("cached sprite '", ssid.get, "'");
153 // now fill animSprites
154 foreach (auto anma2; anims.byKeyValue) {
155 if (anma2.key !in animSprites) animSprites[anma2.key] = new ImgSprite*[][](2); // 2 dirs
156 auto aspx = animSprites[anma2.key];
157 foreach (immutable dir, auto anma; anma2.value) {
158 foreach (StrId ssid; anma) {
159 ImgSprite* spi = null;
160 if (ssid.id != 0) spi = ssid.id in allSprites;
161 aspx[dir] ~= spi;
167 // unload actor graphics
168 void releaseGraphics () {
169 animSprites = null;
170 //allSprites.clear();
173 int nextAnimIdx (StrId state, uint dir, int curidx) {
174 if (dir != 0) dir = 1;
175 if (++curidx <= 0) return 0;
176 if (auto spra = state.id in animSprites) {
177 if (curidx < (*spra).ptr[dir].length) return curidx;
178 return 0;
180 return 0;
183 ImgSprite* animSpr (StrId state, uint dir, int curidx) {
184 if (dir != 0) dir = 1;
185 if (curidx < 0) return null;
186 if (auto spra = state.id in animSprites) {
187 if (curidx >= (*spra).ptr[dir].length) return null;
188 return (*spra).ptr[dir].ptr[curidx];
190 return null;
193 private __gshared uint nextId = 1;
195 this (string ctype, string cname) {
196 classtype = ctype;
197 classname = cname;
198 fullname = classtype~":"~classname;
199 id = nextId++;
202 void clearAllFrames (StrId state) {
203 anims.clear();
206 void clearFrames (StrId state) {
207 anims.remove(state.id);
210 void addFrame (StrId state, uint dir, StrId sprname) {
211 //conwriteln("new frame for '", fullname, "'; state=", state.get, "; sprname=", sprname.get, "; dir=", dir);
212 if (dir > 1) throw new Exception("addFrame: invalid dir");
213 if (state.id !in anims) anims[state.id] = new StrId[][](2);
214 auto aa = anims[state.id];
215 aa[dir] ~= sprname;
218 void setAnimInitFunc (FuncPool.FuncInfo fi) {
219 if (fi is null) return;
220 if (fi.mgtype != ":void") throw new Exception("invalid actor animation init function");
221 fiAnimInit ~= fi;
224 void setInitFunc (FuncPool.FuncInfo fi) {
225 if (fi is null) return;
226 if (fi.mgtype != ":void:Actor") throw new Exception("invalid actor init function");
227 fiInit = fi;
230 void setThinkFunc (FuncPool.FuncInfo fi) {
231 if (fi is null) return;
232 if (fi.mgtype != ":void:Actor") throw new Exception("invalid actor think function");
233 fiThink = fi;
236 void callAnimInit () {
237 foreach (auto fi; fiAnimInit) {
238 //vm.reset();
239 fi();
243 void callInit (ActorId aid) {
244 if (fiInit is null || !aid.valid) return;
245 //vm.reset();
246 //vm.pushUint(aid.id); // arg0
247 //vm.executeFunc(fiInit);
248 fiInit(aid);
251 void callThink (ActorId aid) {
252 if (fiThink is null || !aid.valid) return;
253 //vm.reset();
254 //vm.pushUint(aid.id); // arg0
255 //vm.executeFunc(fiThink);
256 fiThink(aid);
261 // ////////////////////////////////////////////////////////////////////////// //
262 public __gshared ActorDef[string] actordefs; // by fullname
265 public ActorDef findD2DActorDef (ushort mapid) {
266 if (mapid == 0) assert(0);
267 if (mapid == 1 || mapid == 2) return findActorDefByFullName("monster:Player");
268 if (auto dad = mapid in d2dactordefsById) {
269 auto adef = findActorDefByFullName(dad.fullname);
270 if (adef is null) throw new Exception("can't find DACS actor definition for D2D actor '"~dad.fullname~"'");
271 return adef;
273 import std.conv : to;
274 throw new Exception("can't find D2D ActorDef for mapid "~to!string(mapid));
278 public ActorDef findActorDefByFullName (const(char)[] fullname) {
279 if (auto fd = fullname in actordefs) return *fd;
280 return null;
284 public ActorDef findActorDef (const(char)[] ctype, const(char)[] cname) {
285 if (ctype.length+cname.length > 1024) assert(0);
286 char[1025] buf;
287 buf[0..ctype.length] = ctype[];
288 buf[ctype.length] = ':';
289 buf[ctype.length+1..ctype.length+1+cname.length] = cname[];
290 if (auto fd = buf[0..ctype.length+1+cname.length] in actordefs) return *fd;
291 return null;
295 public ActorDef findActorDef (StrId ctype, StrId cname) { return findActorDef(ctype.get, cname.get); }
298 public ActorDef registerActorDef (string classtype, string classname) {
299 string fullname = classtype~":"~classname;
300 if (fullname !in actordefs) actordefs[fullname] = new ActorDef(classtype, classname);
301 if (auto fd = fullname in actordefs) return *fd;
302 assert(0);