scripts restructured; teleswitch now works
[dd2d.git] / data / scripts / api / move.dacs
blob6aeb6cc8a89b5b6fc5475a69495c13dad30f411c
1 module apiMove;
3 import apiActor, apiMap, stdlib;
6 const MAX_YV = 30;
9 // ////////////////////////////////////////////////////////////////////////// //
10 /// check area, half of height
11 public int Z_checkerRHHalf (int x, int y, int r, int h, int function (int tiletype) ccb) {
12   // start tile
13   int sx = max((x-r)/CELW, 0);
14   int sy = max((y-h+1)/CELH, 0);
15   // end tile
16   x = min((x+r)/CELW, FLDW-1);
17   y = min((y-h/2)/CELH, FLDH-1);
18   if (sx > x || sy > y) return -1; // counts as true anyway
19   while (sx <= x) {
20     for (int j = sy; j <= y; ++j) {
21       int res = ccb(mapGetTypeTile(sx, j));
22       if (res) return res;
23     }
24     ++sx;
25   }
26   return 0;
30 public int Z_checkerRHHalfEx (int x, int y, int r, int h, int function (int tilefg, int tiletype) ccb) {
31   // start tile
32   int sx = max((x-r)/CELW, 0);
33   int sy = max((y-h+1)/CELH, 0);
34   // end tile
35   x = min((x+r)/CELW, FLDW-1);
36   y = min((y-h/2)/CELH, FLDH-1);
37   if (sx > x || sy > y) return -1; // counts as true anyway
38   while (sx <= x) {
39     for (int j = sy; j <= y; ++j) {
40       int res = ccb(mapGetTile(LAYER_FRONT, sx, j), mapGetTypeTile(sx, j));
41       if (res) return res;
42     }
43     ++sx;
44   }
45   return 0;
49 // check "under feet" / "above head"
50 public int Z_checkerRHFeetHead (int x, int y, int r, int h, int function (int tiletype) ccb) {
51   //int origx = x;
52   int i = max((x-r)/CELW, 0);
53   x = min((x+r)/CELW, FLDW-1);
54   y = (y-h+1)/CELH;
55   //if (origx >= 160 && origx <= 168 && h > 2) { writeln("Z_checkerRHFeetHead: i=", i, "; x=", x, "; y=", y); }
56   if (y >= FLDH || y < 0) return 0;
57   for (; i <= x; ++i) {
58     //if (origx >= 160 && origx <= 168 && h > 2) { writeln("  i=", i, "; y=", y, "; tt=", mapGetTypeTile(i, y)); }
59     int res = ccb(mapGetTypeTile(i, y));
60     //writeln("  Z_checkerRHFeetHead(", i, ", ", y, ") = ", res);
61     if (res) return res;
62   }
63   return 0;
67 // check the whole occupied area
68 public int Z_checkerRHWhole (int x, int y, int r, int h, int dy, int function (int tiletype) ccb) {
69   int sx = max((x-r)/CELW, 0);
70   int sy = max((y-h+1)/CELH, 0);
71   x = min((x+r)/CELW, FLDW-1);
72   y = min((y+dy)/CELH, FLDH-1);
73   if (sx > x || sy > y) return -1; // counts as true anyway
74   for (int i = sx; i <= x; ++i) {
75     for (int j = sy; j <= y; ++j) {
76       int res = ccb(mapGetTypeTile(i, j));
77       //writeln("  Z_checkerRHWhole(", i, ", ", j, ") = ", res);
78       if (res) return res;
79     }
80   }
81   return 0;
85 // ////////////////////////////////////////////////////////////////////////// //
86 int Z_canbreatheCCB (int fv) {
87   switch (fv) {
88     case TILE_EMPTY:
89     case TILE_DOORO:
90     case TILE_LIFTU:
91     case TILE_LIFTD:
92       return 1;
93     default:
94   }
95   return 0;
98 public int Z_canbreathe (int x, int y, int r, int h) { return (Z_checkerRHHalf(x, y, r, h, &Z_canbreatheCCB) != 0); }
101 // ////////////////////////////////////////////////////////////////////////// //
102 int Z_canstandCCB (int fv) { return (fv == TILE_WALL || fv == TILE_DOORC || fv == TILE_STEP ? 1 : 0); }
104 public int Z_canstand (int x, int y, int r) { return Z_checkerRHFeetHead(x, y, r, 0, &Z_canstandCCB); }
107 // ////////////////////////////////////////////////////////////////////////// //
108 int Z_cangodownCCB (int fv) { return (fv == TILE_STEP ? 1 : 0); }
110 public int Z_cangodown (int x, int y, int r) { return Z_checkerRHFeetHead(x, y, r, 0, &Z_cangodownCCB); }
113 // ////////////////////////////////////////////////////////////////////////// //
114 int Z_hitceilCCB (int fv) {
115   return (getCheatNoDoors ? (fv == TILE_WALL ? 1 : 0) : (fv == TILE_WALL || fv == TILE_DOORC ? 1 : 0));
118 public int Z_hitceil (int x, int y, int r, int h) {
119   //if (x >= 160 && x <= 168) writeln("=== hitceil: x=", x, "; y=", y, "; r=", r, "; h=", h);
120   return Z_checkerRHFeetHead(x, y, r, h+1, &Z_hitceilCCB); // `+1` due to checker specific
124 // ////////////////////////////////////////////////////////////////////////// //
125 int Z_canfitCCB (int fv) { return (fv == TILE_WALL || fv == TILE_DOORC ? 1 : 0); }
127 public int Z_canfit (int x, int y, int r, int h) { return 1-Z_checkerRHWhole(x, y, r, h, 0, &Z_canfitCCB); }
130 // ////////////////////////////////////////////////////////////////////////// //
131 int Z_inliftCCB (int fv) {
132   if (fv == TILE_LIFTU || fv == TILE_LIFTD) return fv-TILE_LIFTU+1;
133   return 0;
136 public int Z_inlift (int x, int y, int r, int h) { return Z_checkerRHWhole(x, y, r, h, -1, &Z_inliftCCB); }
139 // ////////////////////////////////////////////////////////////////////////// //
140 int Z_isblockedCCB (int fv) { return (fv == TILE_MBLOCK ? 1 : 0); }
142 public int Z_isblocked (int x, int y, int r, int h, int xv) { return Z_checkerRHWhole(x, y, r, h, -1, &Z_isblockedCCB); }
145 // ////////////////////////////////////////////////////////////////////////// //
146 int Z_istrappedCCB (int fv) { return (fv == TILE_ACTTRAP ? 1 : 0); }
148 public int Z_istrapped (int x, int y, int r, int h) { return Z_checkerRHWhole(x, y, r, h, -1, &Z_istrappedCCB); }
151 // ////////////////////////////////////////////////////////////////////////// //
152 //static uint8_t wfront; // for splash
153 int Z_inwaterCCB (int fv) {
154   //return (fv >= TILE_WATER && fv <= TILE_ACID2 ? 1 : 0); /* wfront = fv;*/
155   switch (fv) {
156     case TILE_WATER: return Z_WATER_0;
157     case TILE_ACID1: return Z_WATER_1;
158     case TILE_ACID2: return Z_WATER_2;
159     default:
160   }
161   return 0;
164 public int Z_inwater (int x, int y, int r, int h/*, ref int wfront*/) { return Z_checkerRHHalf(x, y, r, h, &Z_inwaterCCB); }
167 int Z_inwaterCCBEx (int fg, int fv) {
168   //return (fv >= TILE_WATER && fv <= TILE_ACID2 ? 1 : 0); /* wfront = fv;*/
169   int res = 0;
170   switch (fv) {
171     case TILE_WATER: res = Z_WATER_0; break;
172     case TILE_ACID1: res = Z_WATER_1; break;
173     case TILE_ACID2: res = Z_WATER_2; break;
174     default:
175   }
176   if (res) {
177     int wt = mapGetWaterTexture(fg);
178     switch (wt) {
179       case 1: res |= Z_WATER_T0; break;
180       case 2: res |= Z_WATER_T1; break;
181       case 3: res |= Z_WATER_T2; break;
182       default:
183     }
184   }
185   return res;
188 public int Z_inwaterEx (int x, int y, int r, int h/*, ref int wfront*/) { return Z_checkerRHHalfEx(x, y, r, h, &Z_inwaterCCBEx); }
191 // ////////////////////////////////////////////////////////////////////////// //
192 int clamp7 (int v) { return (abs(v) <= 7 ? v : (v > 0 ? 7 : -7)); }
194 //int is_dot (Actor me) { return false; }
195 //int is_ghost_player (Actor me) { return false; }
198 public int Z_dec (int n, int delta) {
199   if (abs(n) > delta) {
200     if (n > 0) return n-delta;
201     if (n < 0) return n+delta;
202   }
203   return 0;
206 //#define wvel(v) if ((xv = abs(v)+1) > 5) v = Z_dec(v, xv/2-2)
209 public int Z_moveobj (Actor me) {
210   int xv, yv, lx, ly;
211   int/*uint8_t*/ inw;
213   int st = 0;
214   int x = me.x;
215   int y = me.y;
216   int r = me.radius;
217   int h = me.height;
219   auto cheatNWC = (me.isPlayer ? getCheatNoWallClip() : false);
220   auto cheatNCC = (me.isPlayer ? getCheatNoCeilClip() : false);
221   auto cheatNLC = (me.isPlayer ? getCheatNoLiftClip() : false);
223   if (!cheatNLC) {
224     switch (Z_inlift(x, y, r, h)) {
225       case 0:
226         if (++me.yv > MAX_YV) --me.yv;
227         break;
228       case 1:
229         if (--me.yv < -5) ++me.yv;
230         break;
231       case 2:
232         if (me.yv > 5) --me.yv; else ++me.yv;
233         break;
234       default:
235     }
236   }
238   inw = Z_inwater(x, y, r, h);
239   //writeln("x=", x, "; y=", y, "; r=", r, "; h=", h, "; inw=", inw);
240   if (inw != 0) {
241     st |= Z_INWATER;
242     if ((xv = abs(me.xv)+1) > 5) me.xv = Z_dec(me.xv, xv/2-2);
243     if ((xv = abs(me.yv)+1) > 5) me.yv = Z_dec(me.yv, xv/2-2);
244     if ((xv = abs(me.vx)+1) > 5) me.vx = Z_dec(me.vx, xv/2-2);
245     if ((xv = abs(me.vy)+1) > 5) me.vy = Z_dec(me.vy, xv/2-2);
246   }
248   //writeln("  vx=", me.vx, "; vy=", me.vy);
249   me.vx = Z_dec(me.vx, 1);
250   me.vy = Z_dec(me.vy, 1);
251   //writeln("  vx=", me.vx, "; vy=", me.vy);
253   //writeln("  xv=", me.xv, "; yv=", me.yv);
255   xv = me.xv+me.vx;
256   yv = me.yv+me.vy;
257   //writeln("  xv=", xv, "; yv=", yv);
259   while (xv || yv) {
260     //writeln("  *xv=", xv, "; yv=", yv);
261     if (x < -100 || x >= FLDW*CELW+100 || y < -100 || y >= FLDH*CELH+100) {
262       // out of map
263       st |= Z_FALLOUT;
264     }
266     //writeln("  x=", x, "; xv=", xv, "; c7(xv)=", clamp7(xv));
267     lx = x;
268     x += clamp7(xv);
269     //writeln("  x=", x);
271     if (me.isMonster) {
272       // for monster
273       if (Z_isblocked(x, y, r, h, xv)) st |= Z_BLOCK;
274     }
276     if (!Z_canfit(/*is_dot(me),*/ x, y, r, h)) {
277       if (!cheatNWC) {
278         /*
279         if (gm_climb_stairs && is_player(me)) {
280           // check if we can climb upstairs
281           if (yv == 1 && (xv == 1 || xv == -1)) {
282             if (Z_canfit(me.type, x, y-CELH, r, h) && Z_canfit(me.type, x+Z_sign(xv)*(CELW-1), y-CELH, r, h)) {
283               me.vy = -8;
284               return Z_moveobj(me);
285             }
286           }
287         }
288         */
289         if (xv == 0) x = lx;
290         else if (xv < 0) x = ((lx-r)&0xFFF8)+r;
291         else x = ((lx+r)&0xFFF8)-r+7;
292         xv = me.xv = me.vx = 0;
293         st |= Z_HITWALL;
294       }
295     }
296     xv -= clamp7(xv);
297     //writeln("  xv=", xv);
299     ly = y;
300     y += clamp7(yv);
301     if (yv >= 8) --y;
302     // moving up and hit the ceiling
303     if (!cheatNCC) {
304       if (yv < 0 && Z_hitceil(/*me.type,*/ x, y, r, h)) {
305         //writeln("hitceil: x=", x, "; y=", y);
306         y = ((ly-h+1)&0xFFF8)+h-1;
307         //writeln("  newy=", y);
308         yv = me.vy = 1;
309         me.yv = 0;
310         st |= Z_HITCEIL;
311       }
312       if (yv > 0 && Z_canstand(/*me.type,*/ x, y, r)) {
313         y = ((y+1)&0xFFF8)-1;
314         yv = me.yv = me.vy = 0;
315         st |= Z_HITLAND;
316       }
317     }
318     yv -= clamp7(yv);
319     //writeln("  yv=", yv);
320   }
322   me.x = x;
323   me.y = y;
324   //writeln("  x=", x, "; y=", y);
326   int wtr = Z_inwaterEx(x, y, r, h);
327   if (wtr) {
328     st |= Z_INWATER;
329     if (!inw) st |= Z_HITWATER;
330     st |= wtr;
331   } else if (inw) {
332     st |= Z_HITAIR;
333   }
335   return st;
339 // ////////////////////////////////////////////////////////////////////////// //
340 public void Z_splash (Actor me, int n, int st) {
341   //Z_sound(bulsnd[0], 128);
342   //DOT_water(p->x, p->y-p->h/2, p->xv+p->vx, p->yv+p->vy, n, /*(int)walp[wfront]*/walp[wfront]->wanim-1);
343   //writeln("Z_splash: n=", n, "; wtx=", (st&(Z_WATER_0|Z_WATER_1|Z_WATER_2)));
344   int wtt;
345        if (st&Z_WATER_T0) wtt = 0;
346   else if (st&Z_WATER_T1) wtt = 1;
347   else if (st&Z_WATER_T2) wtt = 2;
348   else return;
349   //writeln("Z_splash: n=", n, "; wtt=", wtt);
350   dotAddWater(me.x, me.y-me.height/2, me.xv+me.vx, me.yv+me.vy, n, wtt);
354 // ////////////////////////////////////////////////////////////////////////// //
355 public void Z_simpleGravity (Actor me) {
356   if (me.flags&AF_NOGRAVITY) return;
357   auto st = Z_moveobj(me);
358   if (st&Z_FALLOUT) { me.actorRemove; return; }
359   if (st&Z_HITWATER) Z_splash(me, me.radius+me.height, st);
363 // ////////////////////////////////////////////////////////////////////////// //
364 public void Z_teleobj (Actor me, int x, int y) {
365   //FX_tfog(p.x, p.y);
366   //FX_tfog((p.x = x), (p.y = y));
367   //Z_sound(telesnd, 128);
368   me.x = x;
369   me.y = y;