OSDN Git Service

new file: 16/v2/CONSOLE.TXT
[proj16/16.git] / 16 / v2 / source / verge / ENGINE / ENTITY.C
1 /*\r
2 Copyright (C) 1998 BJ Eirich (aka vecna)\r
3 This program is free software; you can redistribute it and/or\r
4 modify it under the terms of the GNU General Public License\r
5 as published by the Free Software Foundation; either version 2\r
6 of the License, or (at your option) any later version.\r
7 This program is distributed in the hope that it will be useful,\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
10 See the GNU General Public Lic\r
11 See the GNU General Public License for more details.\r
12 You should have received a copy of the GNU General Public License\r
13 along with this program; if not, write to the Free Software\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
15 */\r
16 \r
17 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\r
18 // CHANGELOG:\r
19 // <zero, 5.6.98>\r
20 // + corrected oversight in movement script management by sticking a hack in\r
21 //   MoveScript().  Bug caused Fx commands to not work sometimes.\r
22 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\r
23 \r
24 #define ENTITY_H\r
25 #include "verge.h"\r
26 \r
27 // ================================= Data ====================================\r
28 \r
29 typedef struct\r
30 {\r
31   int x, y;                            // xwc, ywx position\r
32   word tx, ty;                         // xtc, ytc position\r
33   byte facing;                         // direction entity is facing\r
34   byte moving, movecnt;                // direction entity is moving\r
35   byte frame;                          // bottom-line frame to display\r
36   byte specframe;                      // special-frame set thingo\r
37   byte chrindex, reset;                // CHR index | Reset animation\r
38   byte obsmode1, obsmode2;             // can be obstructed | Is an obstruction\r
39   byte speed, speedct;                 // entity speed, speedcount :)\r
40   byte delayct;                        // animation frame-delay\r
41   char *animofs, *scriptofs;           // anim script | move script\r
42   byte face, actm;                     // auto-face | activation mode\r
43   byte movecode, movescript;           // movement type | movement script\r
44   byte ctr, mode;                      // sub-tile move ctr, mode flag (internal)\r
45   word step, delay;                    // step, delay\r
46   word stepctr, delayctr;              // internal use counters\r
47   word data1, data2, data3;            //\r
48   word data4, data5, data6;            //\r
49   int  actscript;                      // activation script\r
50   int  expand1, expand2;               //\r
51   int  expand3, expand4;               //\r
52   char desc[20];                       // Entity description.\r
53 } entity_r;\r
54 \r
55 typedef struct\r
56 {\r
57   byte *imagedata;                   // CHR frame data\r
58   int fxsize, fysize;                // frame x/y dimensions\r
59   int hx, hy;                        // x/y obstruction hotspot\r
60   int totalframes;                   // total # of frames.\r
61   int lidle, ridle;\r
62   int uidle, didle;\r
63   char lanim[100];\r
64   char ranim[100];\r
65   char uanim[100];\r
66   char danim[100];\r
67 } chrdata;\r
68 \r
69 typedef struct\r
70 {\r
71   char t[60];\r
72 } chrlist_r;\r
73 \r
74 chrlist_r chrlist[100];\r
75 byte nmchr,playernum;\r
76 entity_r *player=0;\r
77 entity_r entity[256];\r
78 byte entities=0;\r
79 chrdata chr[100];\r
80 byte numchrs=0;\r
81 byte entidx[256], cc;\r
82 byte movesuccess;\r
83 \r
84 // ================================= Code ====================================\r
85 \r
86 int ObstructionAt(int tx, int ty)\r
87 {\r
88   if (obstruct[(ty*layer[0].sizex)+tx]) return 1;\r
89   if (tx==-1 || ty==-1) return 1;\r
90   if (tx==layer[0].sizex || ty==layer[0].sizey) return 1;\r
91   return 0;\r
92 }\r
93 \r
94 int Zone(int tx, int ty)\r
95 {\r
96   return zone[(ty*layer[0].sizex)+tx];\r
97 }\r
98 \r
99 void LoadCHR(char *fname, chrdata *c)\r
100 {\r
101   VFILE *f;\r
102   char b, *ptr=0;\r
103   int i;\r
104 \r
105   f=vopen(fname);\r
106   if (!f) err("Could not open CHR file %s.",fname);\r
107   vread(&b, 1, f);\r
108   if (b!=2) err("CHR %s incorrect CHR format version.",fname);\r
109   vread(&c->fxsize, 2, f);\r
110   vread(&c->fysize, 2, f);\r
111   vread(&c->hx, 2, f);\r
112   vread(&c->hy, 2, f);\r
113   vread(strbuf, 4, f);          // skip the hotspot size.\r
114   vread(&c->totalframes, 2, f);\r
115 \r
116   vread(&i, 4, f);\r
117   ptr=(char *) valloc(i, "LoadCHR:ptr", OID_TEMP);\r
118   vread(ptr, i, f);\r
119   c->imagedata=(byte *) valloc(c->fxsize * c->fysize * c->totalframes, "LoadCHR:c->imagedata", OID_IMAGE);\r
120   ReadCompressedLayer1(c->imagedata, c->fxsize * c->fysize * c->totalframes, ptr);\r
121   vfree(ptr);\r
122 \r
123 \r
124   vread(&c->lidle, 4, f);\r
125   vread(&c->ridle, 4, f);\r
126   vread(&c->uidle, 4, f);\r
127   vread(&c->didle, 4, f);\r
128 \r
129   for (b=0; b<4; b++)\r
130   {\r
131     switch (b)\r
132     {\r
133       case 0: ptr=c->lanim; break;\r
134       case 1: ptr=c->ranim; break;\r
135       case 2: ptr=c->uanim; break;\r
136       case 3: ptr=c->danim; break;\r
137     }\r
138     vread(&i, 4, f);\r
139     if (i>100) err("Animation strand too long. %d",i);\r
140     vread(ptr, i, f);\r
141   }\r
142   vclose(f);\r
143 }\r
144 \r
145 int CacheCHR(char *fname)\r
146 {\r
147   LoadCHR(fname, &chr[numchrs]);\r
148   numchrs++;\r
149   return (numchrs-1);\r
150 }\r
151 \r
152 void FreeCHRList()\r
153 {\r
154   int i;\r
155 \r
156   for (i=0; i<numchrs; i++)\r
157     vfree(chr[i].imagedata);\r
158   memset(chr, i, sizeof chr);\r
159 }\r
160 \r
161 void LoadCHRList()\r
162 {\r
163   int i;\r
164 \r
165   for (i=0; i<nmchr; i++)\r
166       if (strlen(chrlist[i].t)) CacheCHR(chrlist[i].t);\r
167 }\r
168 \r
169 void DrawEntity(int i)\r
170 {\r
171   int a, b, dx, dy;\r
172 \r
173   dx=entity[i].x-xwin;\r
174   dy=entity[i].y-ywin;\r
175   a=entity[i].chrindex;\r
176   if (a>=numchrs) return;\r
177   b=entity[i].specframe ? entity[i].specframe : entity[i].frame;\r
178   TCopySpriteClip(dx-chr[a].hx, dy-chr[a].hy, chr[a].fxsize, chr[a].fysize,\r
179                   (byte *) (chr[a].imagedata+(b*chr[a].fxsize*\r
180                   chr[a].fysize)));\r
181 }\r
182 \r
183 static int cmpent(const void* a, const void* b)\r
184 {\r
185   return entity[*(byte*)a].y - entity[*(byte*)b].y;\r
186 }\r
187 \r
188 void RenderEntities()\r
189 {\r
190   int i;\r
191 \r
192   qsort(entidx, cc, 1, cmpent);\r
193   for (i=0; i<cc; i++) DrawEntity(entidx[i]);\r
194 }\r
195 \r
196 int GetArg(entity_r *p)\r
197 {\r
198   int j;\r
199   static char token[10];\r
200 \r
201   j=0;\r
202   while (*p->animofs==' ') p->animofs++;\r
203   while (*p->animofs>=48 && *p->animofs<=57)\r
204   {\r
205     token[j]=*p->animofs;\r
206     p->animofs++;\r
207     j++;\r
208   }\r
209   token[j]=0;\r
210   return atoi(token);\r
211 }\r
212 \r
213 void GetNextCommand(entity_r *p)\r
214 {\r
215   byte s;\r
216 \r
217   while (*p->animofs==' ') p->animofs++;\r
218   s=*p->animofs;\r
219   p->animofs++;\r
220   switch (s)\r
221   {\r
222     case 'F': p->frame=GetArg(p); break;\r
223     case 'W': p->delayct=GetArg(p); break;\r
224     case   0: if (p->moving)\r
225                 switch (p->facing)\r
226                 {\r
227                   case 0: p->animofs=chr[p->chrindex].danim; break;\r
228                   case 1: p->animofs=chr[p->chrindex].uanim; break;\r
229                   case 2: p->animofs=chr[p->chrindex].lanim; break;\r
230                   case 3: p->animofs=chr[p->chrindex].ranim; break;\r
231                 }\r
232               else\r
233                 switch (p->facing)\r
234                 {\r
235                   case 0: p->animofs=0; p->frame=chr[p->chrindex].didle; break;\r
236                   case 1: p->animofs=0; p->frame=chr[p->chrindex].uidle; break;\r
237                   case 2: p->animofs=0; p->frame=chr[p->chrindex].lidle; break;\r
238                   case 3: p->animofs=0; p->frame=chr[p->chrindex].ridle; break;\r
239                 }\r
240               p->delayct=0; break;\r
241   }\r
242 }\r
243 \r
244 void AnimateEntity(entity_r *p)\r
245 {\r
246   if (!p->animofs && p->moving)\r
247   {\r
248      switch (p->facing)\r
249      {\r
250        case 0: p->animofs=chr[p->chrindex].danim; break;\r
251        case 1: p->animofs=chr[p->chrindex].uanim; break;\r
252        case 2: p->animofs=chr[p->chrindex].lanim; break;\r
253        case 3: p->animofs=chr[p->chrindex].ranim; break;\r
254      }\r
255      p->delayct=0;\r
256   }\r
257   if (!p->animofs && !p->moving)\r
258   {\r
259      switch (p->facing)\r
260      {\r
261        case 0: p->animofs=0; p->frame=chr[p->chrindex].didle; break;\r
262        case 1: p->animofs=0; p->frame=chr[p->chrindex].uidle; break;\r
263        case 2: p->animofs=0; p->frame=chr[p->chrindex].lidle; break;\r
264        case 3: p->animofs=0; p->frame=chr[p->chrindex].ridle; break;\r
265      }\r
266      p->delayct=0;\r
267   }\r
268   if (p->delayct)\r
269   {\r
270     p->delayct--;\r
271   }\r
272   else GetNextCommand(p);\r
273 }\r
274 \r
275 int EntityAt(int ex, int ey)\r
276 { int i;\r
277 \r
278   for (i=0; i<cc; i++)\r
279   {\r
280     if (&entity[entidx[i]]==player) continue;\r
281     if (ex==entity[entidx[i]].tx && ey==entity[entidx[i]].ty)\r
282         return entidx[i]+1;\r
283   }\r
284   return 0;\r
285 }\r
286 \r
287 int EntityObsAt(int ex, int ey)\r
288 { int i;\r
289 \r
290   for (i=0; i<cc; i++)\r
291   {\r
292     if (&entity[entidx[i]]==player) continue;\r
293     if (ex==entity[entidx[i]].tx && ey==entity[entidx[i]].ty &&\r
294         entity[entidx[i]].obsmode2)\r
295         return entidx[i]+1;\r
296   }\r
297   return 0;\r
298 }\r
299 \r
300 int AEntityObsAt(int ex, int ey)\r
301 { int i;\r
302 \r
303   for (i=0; i<cc; i++)\r
304   {\r
305     if (ex==entity[entidx[i]].tx && ey==entity[entidx[i]].ty &&\r
306         entity[entidx[i]].obsmode2)\r
307         return entidx[i]+1;\r
308   }\r
309   return 0;\r
310 }\r
311 \r
312 void SiftEntities()\r
313 { int i, dx, dy;\r
314 \r
315   memset(&entidx, 0, 256); cc=0;\r
316   for (i=0; i<entities; i++)\r
317   {\r
318     dx=entity[i].x-xwin+16;\r
319     dy=entity[i].y-ywin+16;\r
320 \r
321     if (dx<0 || dx>sx+chr[entity[i].chrindex].fxsize) continue;\r
322     if (dy<0 || dy>sy+chr[entity[i].chrindex].fysize) continue;\r
323     entidx[cc]=i; cc++;\r
324   }\r
325 }\r
326 \r
327 void MoveRight(int i)\r
328 {\r
329   int tx,ty;\r
330 \r
331   tx=entity[i].tx+1; ty=entity[i].ty;\r
332   if (entity[i].obsmode1 && (ObstructionAt(tx,ty) || AEntityObsAt(tx,ty)))\r
333      { movesuccess=0; return; }\r
334   if (entity[i].facing!=3)\r
335   {\r
336     entity[i].delayct=0;\r
337     entity[i].animofs=0;\r
338   }\r
339   entity[i].x++; entity[i].facing=3; entity[i].moving=4; entity[i].ctr=15;\r
340   entity[i].tx++; movesuccess=1; entity[i].reset=0;\r
341 }\r
342 \r
343 void MoveLeft(int i)\r
344 {\r
345   int tx, ty;\r
346 \r
347   tx=entity[i].tx-1; ty=entity[i].ty;\r
348   if (entity[i].obsmode1 && (ObstructionAt(tx,ty) || AEntityObsAt(tx,ty)))\r
349      { movesuccess=0; return; }\r
350 \r
351   if (entity[i].facing!=2)\r
352   {\r
353     entity[i].delayct=0;\r
354     entity[i].animofs=0;\r
355   }\r
356   entity[i].x--; entity[i].facing=2; entity[i].moving=3; entity[i].ctr=15;\r
357   entity[i].tx--; movesuccess=1; entity[i].reset=0;\r
358 }\r
359 \r
360 void MoveUp(int i)\r
361 {\r
362   int tx, ty;\r
363 \r
364   tx=entity[i].tx; ty=entity[i].ty-1;\r
365   if (entity[i].obsmode1 && (ObstructionAt(tx,ty) || AEntityObsAt(tx,ty)))\r
366      { movesuccess=0; return; }\r
367   if (entity[i].facing!=1)\r
368   {\r
369     entity[i].delayct=0;\r
370     entity[i].animofs=0;\r
371   }\r
372   entity[i].y--; entity[i].facing=1; entity[i].moving=2; entity[i].ctr=15;\r
373   entity[i].ty--; movesuccess=1; entity[i].reset=0;\r
374 }\r
375 \r
376 void MoveDown(int i)\r
377 {\r
378   int tx, ty;\r
379 \r
380   tx=entity[i].tx; ty=entity[i].ty+1;\r
381   if (entity[i].obsmode1 && (ObstructionAt(tx,ty) || AEntityObsAt(tx,ty)))\r
382      { movesuccess=0; return; }\r
383   if (entity[i].facing!=0)\r
384   {\r
385     entity[i].delayct=0;\r
386     entity[i].animofs=0;\r
387   }\r
388   entity[i].y++; entity[i].facing=0; entity[i].moving=1; entity[i].ctr=15;\r
389   entity[i].ty++; movesuccess=1; entity[i].reset=0;\r
390 }\r
391 \r
392 void Wander1(int i)\r
393 {\r
394   if (!entity[i].data1)\r
395   {\r
396     entity[i].data2=rnd(0,3);\r
397     entity[i].data1=entity[i].step+1;\r
398   }\r
399   if (entity[i].data1==1)\r
400   {\r
401     entity[i].delayctr++;\r
402     if (entity[i].delayctr>=entity[i].delay)\r
403        entity[i].data1=0;\r
404     return;\r
405   }\r
406   if (entity[i].data1>1)\r
407   {\r
408     switch(entity[i].data2)\r
409     {\r
410       case 0: MoveUp(i); break;\r
411       case 1: MoveDown(i); break;\r
412       case 2: MoveLeft(i); break;\r
413       case 3: MoveRight(i); break;\r
414     }\r
415     entity[i].data1--;\r
416     if (entity[i].data1==1)\r
417     {\r
418       entity[i].delayctr=0;\r
419       entity[i].animofs=0;\r
420       entity[i].delayct=0;\r
421     }\r
422   }\r
423 }\r
424 \r
425 void Wander2(int i)\r
426 {\r
427   if (!entity[i].data1)\r
428   {\r
429     entity[i].data3=rnd(0,3);\r
430     entity[i].data1=entity[i].step+1;\r
431   }\r
432   if (entity[i].data1==1)\r
433   {\r
434     entity[i].delayctr++;\r
435     if (entity[i].delayctr>=entity[i].delay)\r
436        entity[i].data1=0;\r
437     return;\r
438   }\r
439   if (entity[i].data1>1)\r
440   {\r
441     switch(entity[i].data3)\r
442     {\r
443       case 0: if (Zone(entity[i].tx,entity[i].ty-1)==entity[i].data2) MoveUp(i); break;\r
444       case 1: if (Zone(entity[i].tx,entity[i].ty+1)==entity[i].data2) MoveDown(i); break;\r
445       case 2: if (Zone(entity[i].tx-1,entity[i].ty)==entity[i].data2) MoveLeft(i); break;\r
446       case 3: if (Zone(entity[i].tx+1,entity[i].ty)==entity[i].data2) MoveRight(i); break;\r
447      }\r
448     entity[i].data1--;\r
449     if (entity[i].data1==1) entity[i].delayctr=0;\r
450   }\r
451 }\r
452 \r
453 void Wander3(int i)\r
454 {\r
455   if (!entity[i].data1)\r
456   {\r
457     entity[i].data2=rnd(0,3);\r
458     entity[i].data1=entity[i].step+1;\r
459   }\r
460   if (entity[i].data1==1)\r
461   {\r
462     entity[i].delayctr++;\r
463     if (entity[i].delayctr>=entity[i].delay)\r
464        entity[i].data1=0;\r
465     return;\r
466   }\r
467   if (entity[i].data1>1)\r
468   {\r
469     switch(entity[i].data2)\r
470     {\r
471       case 0: if (entity[i].ty>entity[i].data3) MoveUp(i); break;\r
472       case 1: if (entity[i].ty<entity[i].data6) MoveDown(i); break;\r
473       case 2: if (entity[i].tx>entity[i].data2) MoveLeft(i); break;\r
474       case 3: if (entity[i].tx<entity[i].data5) MoveRight(i); break;\r
475     }\r
476     entity[i].data1--;\r
477     if (entity[i].data1==1) entity[i].delayct=0;\r
478   }\r
479 }\r
480 \r
481 void Whitespace(int i)\r
482 {\r
483   while (*entity[i].scriptofs==' ')\r
484     entity[i].scriptofs++;\r
485 }\r
486 \r
487 void GetArgMS(int i)\r
488 { int j;\r
489   char token[10];\r
490 \r
491   j=0;\r
492   Whitespace(i);\r
493   while (*entity[i].scriptofs>=48 && *entity[i].scriptofs<=57)\r
494   {\r
495     token[j]=*entity[i].scriptofs;\r
496     entity[i].scriptofs++;\r
497     j++;\r
498   }\r
499   token[j]=0;\r
500   entity[i].data1=atoi(token);\r
501 }\r
502 \r
503 void GetNextCommandMS(int i)\r
504 { unsigned char s;\r
505 \r
506   Whitespace(i);\r
507   s=*entity[i].scriptofs;\r
508   entity[i].scriptofs++;\r
509   switch (s)\r
510   {\r
511     case 'U': entity[i].mode=1; GetArgMS(i); break;\r
512     case 'D': entity[i].mode=2; GetArgMS(i); break;\r
513     case 'L': entity[i].mode=3; GetArgMS(i); break;\r
514     case 'R': entity[i].mode=4; GetArgMS(i); break;\r
515     case 'S': entity[i].mode=5; GetArgMS(i); break;\r
516     case 'W': entity[i].mode=6; GetArgMS(i); entity[i].animofs=0;\r
517               entity[i].delayct=0; break;\r
518     case 0:   switch (entity[i].facing)\r
519               {\r
520                 case 0: entity[i].animofs=0; entity[i].frame=chr[entity[i].chrindex].didle; break;\r
521                 case 1: entity[i].animofs=0; entity[i].frame=chr[entity[i].chrindex].uidle; break;\r
522                 case 2: entity[i].animofs=0; entity[i].frame=chr[entity[i].chrindex].lidle; break;\r
523                 case 3: entity[i].animofs=0; entity[i].frame=chr[entity[i].chrindex].ridle; break;\r
524               }\r
525               entity[i].movecode=0; entity[i].mode=7; entity[i].data1=0;\r
526               entity[i].scriptofs=0; entity[i].delayct=0; break;\r
527     case 'C': entity[i].mode=8; GetArgMS(i); break;\r
528     case 'B': entity[i].mode=9; break;\r
529     case 'X': entity[i].mode=10; GetArgMS(i); break;\r
530     case 'Y': entity[i].mode=11; GetArgMS(i); break;\r
531     case 'F': entity[i].mode=12; GetArgMS(i); break;\r
532     case 'Z': entity[i].mode=13; GetArgMS(i); break;\r
533     default: err("Invalid entity movement script.");\r
534   }\r
535 }\r
536 \r
537 void MoveScript(int i)\r
538 {\r
539   if (!entity[i].scriptofs) entity[i].scriptofs=(char *) (int) ms+(int) msbuf[entity[i].movescript];\r
540   if (!entity[i].mode) GetNextCommandMS(i);\r
541 \r
542   switch(entity[i].mode)\r
543   {\r
544     case 1: MoveUp(i); if (movesuccess) entity[i].data1--; break;\r
545     case 2: MoveDown(i); if (movesuccess) entity[i].data1--; break;\r
546     case 3: MoveLeft(i); if (movesuccess) entity[i].data1--; break;\r
547     case 4: MoveRight(i); if (movesuccess) entity[i].data1--; break;\r
548     case 5: entity[i].speed=entity[i].data1; entity[i].data1=0; break;\r
549     case 6: entity[i].data1--; break;\r
550     case 7: return;\r
551     case 8: ExecuteEvent(entity[i].data1); entity[i].data1=0; break;\r
552     case 9: entity[i].scriptofs=(char *) (int) ms+(int) msbuf[entity[i].movescript];\r
553             entity[i].data1=0; break;\r
554     case 10: if (entity[i].tx<entity[i].data1) MoveRight(i);\r
555              if (entity[i].tx>entity[i].data1) MoveLeft(i);\r
556              if (entity[i].tx==entity[i].data1) entity[i].data1=0; break;\r
557              break;\r
558     case 11: if (entity[i].ty<entity[i].data1) MoveDown(i);\r
559              if (entity[i].ty>entity[i].data1) MoveUp(i);\r
560              if (entity[i].ty==entity[i].data1) entity[i].data1=0; break;\r
561              break;\r
562     case 12: entity[i].facing=entity[i].data1;\r
563              entity[i].data1=0;\r
564              //--- zero 5.6.99\r
565              switch(entity[i].facing)\r
566              {\r
567                case 0: entity[i].frame=chr[entity[i].chrindex].didle; break;\r
568                case 1: entity[i].frame=chr[entity[i].chrindex].uidle;        break;\r
569                case 2: entity[i].frame=chr[entity[i].chrindex].lidle; break;\r
570                case 3: entity[i].frame=chr[entity[i].chrindex].ridle; break;\r
571              }\r
572              //---\r
573              break;\r
574     case 13: entity[i].specframe=entity[i].data1;\r
575              entity[i].data1=0; break;\r
576   }\r
577   if (!entity[i].data1) entity[i].mode=0;\r
578 }\r
579 \r
580 void TestActive(int i)\r
581 {\r
582   int dx, dy;\r
583 \r
584   dx=abs(entity[i].x - player->x);\r
585   dy=abs(entity[i].y - player->y);\r
586   if ((dx<=16 && dy<=3) || (dx<=3 && dy<=16))\r
587   {\r
588     if (!entity[i].expand4 && !invc)\r
589     {\r
590       entity[i].expand4=1;\r
591       ExecuteEvent(entity[i].actscript);\r
592     }\r
593   }\r
594   else\r
595     entity[i].expand4=0;\r
596 }\r
597 \r
598 void ProcessEntity1(int i)\r
599 {\r
600   entity[i].speedct=0;\r
601   if (entity[i].actm) TestActive(i);\r
602 \r
603   if (!entity[i].moving)\r
604   {\r
605      switch(entity[i].movecode)\r
606      {\r
607        case 0: return;\r
608        case 1: Wander1(i); break;\r
609        case 2: Wander2(i); break;\r
610        case 3: Wander3(i); break;\r
611        case 4: MoveScript(i); break;\r
612        default: err("unknown entity movement pattern.");\r
613      }\r
614      if (!entity[i].reset) return;\r
615   }\r
616 \r
617   if (entity[i].reset)\r
618   {\r
619     entity[i].animofs=0;\r
620     entity[i].delayct=0;\r
621     entity[i].reset=0;\r
622   }\r
623 \r
624   if (entity[i].moving)\r
625   {\r
626       if (entity[i].moving==1)\r
627       { entity[i].y++; entity[i].ctr--; AnimateEntity(&entity[i]); }\r
628       if (entity[i].moving==2)\r
629       { entity[i].y--; entity[i].ctr--; AnimateEntity(&entity[i]); }\r
630       if (entity[i].moving==4)\r
631       { entity[i].x++; entity[i].ctr--; AnimateEntity(&entity[i]); }\r
632       if (entity[i].moving==3)\r
633       { entity[i].x--; entity[i].ctr--; AnimateEntity(&entity[i]); }\r
634       if (!entity[i].ctr) { entity[i].reset=1; entity[i].moving=0; }\r
635    }\r
636 }\r
637 \r
638 void ProcessEntity(int i)\r
639 { int j;\r
640 \r
641   if (player==&entity[i]) return;\r
642   if (entity[i].speed<4)\r
643   {\r
644     switch (entity[i].speed)\r
645     {\r
646       case 1: if (entity[i].speedct<3) { entity[i].speedct++; return; }\r
647       case 2: if (entity[i].speedct<2) { entity[i].speedct++; return; }\r
648       case 3: if (entity[i].speedct<1) { entity[i].speedct++; return; }\r
649     }\r
650   }\r
651   if (entity[i].speed<5)\r
652   {\r
653     ProcessEntity1(i);\r
654     entity[i].speedct=0;\r
655   }\r
656   switch (entity[i].speed)\r
657   {\r
658     case 5: for (j=0; j<2; j++) { ProcessEntity1(i); } return;\r
659     case 6: for (j=0; j<3; j++) { ProcessEntity1(i); } return;\r
660     case 7: for (j=0; j<4; j++) { ProcessEntity1(i); } return;\r
661   }\r
662 }\r
663 \r
664 void ProcessEntities()\r
665 {\r
666   int i;\r
667 \r
668   SiftEntities();\r
669   for (i=0; i<entities; i++) ProcessEntity(i);\r
670 }\r
671 \r
672 void EntityStat()\r
673 {\r
674   Con_NextLine();\r
675   sprintf(strbuf,"There are \82%d~ entities on this map.",entities);\r
676   Con_Printf(strbuf);\r
677   sprintf(strbuf,"\82%d~ of those are onscreen / active.",cc);\r
678   Con_Printf(strbuf);\r
679 }\r
680 \r
681 void ListActiveEnts()\r
682 { int i;\r
683 \r
684   Con_NextLine();\r
685   Con_Printf("Active entities:");\r
686   for (i=0; i<cc; i++)\r
687   {\r
688     sprintf(strbuf,"\82%d~",entidx[i]);\r
689     Con_Printf(strbuf);\r
690   }\r
691 }\r
692 \r
693 void EntityS()\r
694 { int i;\r
695 \r
696   i=atoi((char *) args[1]);\r
697   Con_NextLine();\r
698 \r
699   sprintf(strbuf,"Desc: \82%s~", entity[i].desc); Con_Printf(strbuf);\r
700   sprintf(strbuf,"tx: \82%d~ ty: \82%d~", entity[i].tx, entity[i].ty); Con_Printf(strbuf);\r
701   sprintf(strbuf,"CHR index: %d", entity[i].chrindex); Con_Printf(strbuf);\r
702 }\r
703 \r
704 int AllocateEntity(int x1, int y1, char *fname)\r
705 {\r
706   entity[entities].chrindex=CacheCHR(fname);\r
707   entity[entities].x=x1*16;\r
708   entity[entities].y=y1*16;\r
709   entity[entities].tx=x1;\r
710   entity[entities].ty=y1;\r
711   entity[entities].speed=4;\r
712   entity[entities].obsmode1=1;\r
713   entity[entities].obsmode2=1;\r
714   entities++;\r
715   return (entities-1);\r
716 }\r