added license to scripts and shaders
[dd2d.git] / data / scripts / api / move.dacs
blobef79fe0afce72815a96da0cf4f95564c8aeb73b2
1 /* DooM2D: Midnight on the Firing Line
2  * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3  * Understanding is not required. Only obedience.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 module apiMove;
20 import apiActor, apiMap, stdlib;
21 import apiPlayer, apiMonster;
24 const MAX_YV = 30;
27 // ////////////////////////////////////////////////////////////////////////// //
28 /// check area, half of height
29 public int Z_checkerRHHalf (int x, int y, int r, int h, int function (int tiletype) ccb) {
30   // start tile
31   int sx = max((x-r)/CELW, 0);
32   int sy = max((y-h+1)/CELH, 0);
33   // end tile
34   x = min((x+r)/CELW, FLDW-1);
35   y = min((y-h/2)/CELH, FLDH-1);
36   if (sx > x || sy > y) return -1; // counts as true anyway
37   while (sx <= x) {
38     for (int j = sy; j <= y; ++j) {
39       int res = ccb(mapGetTypeTile(sx, j));
40       if (res) return res;
41     }
42     ++sx;
43   }
44   return 0;
48 public int Z_checkerRHHalfEx (int x, int y, int r, int h, int function (int tilefg, int tiletype) ccb) {
49   // start tile
50   int sx = max((x-r)/CELW, 0);
51   int sy = max((y-h+1)/CELH, 0);
52   // end tile
53   x = min((x+r)/CELW, FLDW-1);
54   y = min((y-h/2)/CELH, FLDH-1);
55   if (sx > x || sy > y) return -1; // counts as true anyway
56   while (sx <= x) {
57     for (int j = sy; j <= y; ++j) {
58       int res = ccb(mapGetTile(LAYER_FRONT, sx, j), mapGetTypeTile(sx, j));
59       if (res) return res;
60     }
61     ++sx;
62   }
63   return 0;
67 // check "under feet" / "above head"
68 public int Z_checkerRHFeetHead (int x, int y, int r, int h, int function (int tiletype) ccb) {
69   //int origx = x;
70   int i = max((x-r)/CELW, 0);
71   x = min((x+r)/CELW, FLDW-1);
72   y = (y-h+1)/CELH;
73   //if (origx >= 160 && origx <= 168 && h > 2) { writeln("Z_checkerRHFeetHead: i=", i, "; x=", x, "; y=", y); }
74   if (y >= FLDH || y < 0) return 0;
75   for (; i <= x; ++i) {
76     //if (origx >= 160 && origx <= 168 && h > 2) { writeln("  i=", i, "; y=", y, "; tt=", mapGetTypeTile(i, y)); }
77     int res = ccb(mapGetTypeTile(i, y));
78     //writeln("  Z_checkerRHFeetHead(", i, ", ", y, ") = ", res);
79     if (res) return res;
80   }
81   return 0;
85 // check the whole occupied area
86 public int Z_checkerRHWhole (int x, int y, int r, int h, int dy, int function (int tiletype) ccb) {
87   int sx = max((x-r)/CELW, 0);
88   int sy = max((y-h+1)/CELH, 0);
89   x = min((x+r)/CELW, FLDW-1);
90   y = min((y+dy)/CELH, FLDH-1);
91   if (sx > x || sy > y) return -1; // counts as true anyway
92   for (int i = sx; i <= x; ++i) {
93     for (int j = sy; j <= y; ++j) {
94       int res = ccb(mapGetTypeTile(i, j));
95       //writeln("  Z_checkerRHWhole(", i, ", ", j, ") = ", res);
96       if (res) return res;
97     }
98   }
99   return 0;
103 // ////////////////////////////////////////////////////////////////////////// //
104 int Z_canbreatheCCB (int fv) {
105   switch (fv) {
106     case TILE_EMPTY:
107     case TILE_DOORO:
108     case TILE_LIFTU:
109     case TILE_LIFTD:
110       return 1;
111     default:
112   }
113   return 0;
116 public int Z_canbreathe (int x, int y, int r, int h) { return (Z_checkerRHHalf(x, y, r, h, &Z_canbreatheCCB) != 0); }
119 // ////////////////////////////////////////////////////////////////////////// //
120 int Z_canstandCCB (int fv) { return (fv == TILE_WALL || fv == TILE_DOORC || fv == TILE_STEP ? 1 : 0); }
122 public int Z_canstand (int x, int y, int r) { return Z_checkerRHFeetHead(x, y, r, 0, &Z_canstandCCB); }
125 // ////////////////////////////////////////////////////////////////////////// //
126 int Z_cangodownCCB (int fv) { return (fv == TILE_STEP ? 1 : 0); }
128 public int Z_cangodown (int x, int y, int r) { return Z_checkerRHFeetHead(x, y, r, 0, &Z_cangodownCCB); }
131 // ////////////////////////////////////////////////////////////////////////// //
132 int Z_hitceilCCB (int fv) {
133   return (getCheatNoDoors ? (fv == TILE_WALL ? 1 : 0) : (fv == TILE_WALL || fv == TILE_DOORC ? 1 : 0));
136 public int Z_hitceil (int x, int y, int r, int h) {
137   //if (x >= 160 && x <= 168) writeln("=== hitceil: x=", x, "; y=", y, "; r=", r, "; h=", h);
138   return Z_checkerRHFeetHead(x, y, r, h+1, &Z_hitceilCCB); // `+1` due to checker specific
142 // ////////////////////////////////////////////////////////////////////////// //
143 int Z_canfitCCB (int fv) { return (fv == TILE_WALL || fv == TILE_DOORC ? 1 : 0); }
145 public int Z_canfit (int x, int y, int r, int h) { return 1-Z_checkerRHWhole(x, y, r, h, 0, &Z_canfitCCB); }
148 // ////////////////////////////////////////////////////////////////////////// //
149 int Z_inliftCCB (int fv) {
150   if (fv == TILE_LIFTU || fv == TILE_LIFTD) return fv-TILE_LIFTU+1;
151   return 0;
154 public int Z_inlift (int x, int y, int r, int h) { return Z_checkerRHWhole(x, y, r, h, -1, &Z_inliftCCB); }
157 // ////////////////////////////////////////////////////////////////////////// //
158 int Z_isblockedCCB (int fv) { return (fv == TILE_MBLOCK ? 1 : 0); }
160 public int Z_isblocked (int x, int y, int r, int h, int xv) { return Z_checkerRHWhole(x, y, r, h, -1, &Z_isblockedCCB); }
163 // ////////////////////////////////////////////////////////////////////////// //
164 int Z_istrappedCCB (int fv) { return (fv == TILE_ACTTRAP ? 1 : 0); }
166 public int Z_istrapped (int x, int y, int r, int h) { return Z_checkerRHWhole(x, y, r, h, -1, &Z_istrappedCCB); }
169 // ////////////////////////////////////////////////////////////////////////// //
170 //static uint8_t wfront; // for splash
171 int Z_inwaterCCB (int fv) {
172   //return (fv >= TILE_WATER && fv <= TILE_ACID2 ? 1 : 0); /* wfront = fv;*/
173   switch (fv) {
174     case TILE_WATER: return Z_WATER_0;
175     case TILE_ACID1: return Z_WATER_1;
176     case TILE_ACID2: return Z_WATER_2;
177     default:
178   }
179   return 0;
182 public int Z_inwater (int x, int y, int r, int h/*, ref int wfront*/) { return Z_checkerRHHalf(x, y, r, h, &Z_inwaterCCB); }
185 int Z_inwaterCCBEx (int fg, int fv) {
186   //return (fv >= TILE_WATER && fv <= TILE_ACID2 ? 1 : 0); /* wfront = fv;*/
187   int res = 0;
188   switch (fv) {
189     case TILE_WATER: res = Z_WATER_0; break;
190     case TILE_ACID1: res = Z_WATER_1; break;
191     case TILE_ACID2: res = Z_WATER_2; break;
192     default:
193   }
194   if (res) {
195     int wt = mapGetWaterTexture(fg);
196     switch (wt) {
197       case 1: res |= Z_WATER_T0; break;
198       case 2: res |= Z_WATER_T1; break;
199       case 3: res |= Z_WATER_T2; break;
200       default:
201     }
202   }
203   return res;
206 public int Z_inwaterEx (int x, int y, int r, int h/*, ref int wfront*/) { return Z_checkerRHHalfEx(x, y, r, h, &Z_inwaterCCBEx); }
209 // ////////////////////////////////////////////////////////////////////////// //
210 int clamp7 (int v) { return (abs(v) <= 7 ? v : (v > 0 ? 7 : -7)); }
212 //int is_dot (Actor me) { return false; }
213 //int is_ghost_player (Actor me) { return false; }
216 public int Z_dec (int n, int delta) {
217   if (abs(n) > delta) {
218     if (n > 0) return n-delta;
219     if (n < 0) return n+delta;
220   }
221   return 0;
224 //#define wvel(v) if ((xv = abs(v)+1) > 5) v = Z_dec(v, xv/2-2)
227 public int Z_moveobj (Actor me) {
228   if (me.dead) return 0;
230   int xv, yv, lx, ly;
231   int/*uint8_t*/ inw;
233   int st = 0;
234   int x = me.x;
235   int y = me.y;
236   int r = me.radius;
237   int h = me.height;
239   auto cheatNWC = (me.isPlayer ? getCheatNoWallClip() : false);
240   auto cheatNCC = (me.isPlayer ? getCheatNoCeilClip() : false);
241   auto cheatNLC = (me.isPlayer ? getCheatNoLiftClip() : false);
243   if (!cheatNLC) {
244     switch (Z_inlift(x, y, r, h)) {
245       case 0:
246         if (++me.yv > MAX_YV) --me.yv;
247         break;
248       case 1:
249         if (--me.yv < -5) ++me.yv;
250         break;
251       case 2:
252         if (me.yv > 5) --me.yv; else ++me.yv;
253         break;
254       default:
255     }
256   }
258   inw = Z_inwater(x, y, r, h);
259   //writeln("x=", x, "; y=", y, "; r=", r, "; h=", h, "; inw=", inw);
260   if (inw != 0) {
261     st |= Z_INWATER;
262     if ((xv = abs(me.xv)+1) > 5) me.xv = Z_dec(me.xv, xv/2-2);
263     if ((xv = abs(me.yv)+1) > 5) me.yv = Z_dec(me.yv, xv/2-2);
264     if ((xv = abs(me.vx)+1) > 5) me.vx = Z_dec(me.vx, xv/2-2);
265     if ((xv = abs(me.vy)+1) > 5) me.vy = Z_dec(me.vy, xv/2-2);
266   }
268   //writeln("  vx=", me.vx, "; vy=", me.vy);
269   me.vx = Z_dec(me.vx, 1);
270   me.vy = Z_dec(me.vy, 1);
271   //writeln("  vx=", me.vx, "; vy=", me.vy);
273   //writeln("  xv=", me.xv, "; yv=", me.yv);
275   xv = me.xv+me.vx;
276   yv = me.yv+me.vy;
277   //writeln("  xv=", xv, "; yv=", yv);
279   while (xv || yv) {
280     //writeln("  *xv=", xv, "; yv=", yv);
281     if (x < -100 || x >= FLDW*CELW+100 || y < -100 || y >= FLDH*CELH+100) {
282       // out of map
283       st |= Z_FALLOUT;
284     }
286     //writeln("  x=", x, "; xv=", xv, "; c7(xv)=", clamp7(xv));
287     lx = x;
288     x += clamp7(xv);
289     //writeln("  x=", x);
291     if (me.isMonster) {
292       // for monster
293       if (Z_isblocked(x, y, r, h, xv)) st |= Z_BLOCK;
294     }
296     if (!Z_canfit(/*is_dot(me),*/ x, y, r, h)) {
297       if (!cheatNWC) {
298         /*
299         if (gm_climb_stairs && is_player(me)) {
300           // check if we can climb upstairs
301           if (yv == 1 && (xv == 1 || xv == -1)) {
302             if (Z_canfit(me.type, x, y-CELH, r, h) && Z_canfit(me.type, x+Z_sign(xv)*(CELW-1), y-CELH, r, h)) {
303               me.vy = -8;
304               return Z_moveobj(me);
305             }
306           }
307         }
308         */
309         if (xv == 0) x = lx;
310         else if (xv < 0) x = ((lx-r)&0xFFF8)+r;
311         else x = ((lx+r)&0xFFF8)-r+7;
312         xv = me.xv = me.vx = 0;
313         st |= Z_HITWALL;
314       }
315     }
316     xv -= clamp7(xv);
317     //writeln("  xv=", xv);
319     ly = y;
320     y += clamp7(yv);
321     if (yv >= 8) --y;
322     // moving up and hit the ceiling
323     if (!cheatNCC) {
324       if (yv < 0 && Z_hitceil(/*me.type,*/ x, y, r, h)) {
325         //writeln("hitceil: x=", x, "; y=", y);
326         y = ((ly-h+1)&0xFFF8)+h-1;
327         //writeln("  newy=", y);
328         yv = me.vy = 1;
329         me.yv = 0;
330         st |= Z_HITCEIL;
331       }
332       if (yv > 0 && Z_canstand(/*me.type,*/ x, y, r)) {
333         y = ((y+1)&0xFFF8)-1;
334         yv = me.yv = me.vy = 0;
335         st |= Z_HITLAND;
336       }
337     }
338     yv -= clamp7(yv);
339     //writeln("  yv=", yv);
340   }
342   me.x = x;
343   me.y = y;
344   //writeln("  x=", x, "; y=", y);
346   int wtr = Z_inwaterEx(x, y, r, h);
347   if (wtr) {
348     st |= Z_INWATER;
349     if (!inw) st |= Z_HITWATER;
350     st |= wtr;
351   } else if (inw) {
352     st |= Z_HITAIR;
353   }
355   return st;
359 // ////////////////////////////////////////////////////////////////////////// //
360 public void Z_splash (Actor me, int n, int st) {
361   if (me.dead) return;
362   //Z_sound(bulsnd[0], 128);
363   //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);
364   //writeln("Z_splash: n=", n, "; wtx=", (st&(Z_WATER_0|Z_WATER_1|Z_WATER_2)));
365   int wtt;
366        if (st&Z_WATER_T0) wtt = 0;
367   else if (st&Z_WATER_T1) wtt = 1;
368   else if (st&Z_WATER_T2) wtt = 2;
369   else return;
370   //writeln("Z_splash: n=", n, "; wtt=", wtt);
371   dotAddWater(me.x, me.y-me.height/2, me.xv+me.vx, me.yv+me.vy, n, wtt);
375 // ////////////////////////////////////////////////////////////////////////// //
376 public void Z_simpleGravity (Actor me) {
377   if (me.dead) return;
378   if (me.flags&AF_NOGRAVITY) return;
379   auto st = Z_moveobj(me);
380   if (st&Z_FALLOUT) { me.actorMarkDead(); return; }
381   if (st&Z_HITWATER) Z_splash(me, me.radius+me.height, st);
385 // ////////////////////////////////////////////////////////////////////////// //
386 public void Z_teleobj (Actor me, int x, int y) {
387   if (me.dead) return;
388   //FX_tfog(p.x, p.y);
389   //FX_tfog((p.x = x), (p.y = y));
390   //Z_sound(telesnd, 128);
391   me.x = x;
392   me.y = y;
396 // ////////////////////////////////////////////////////////////////////////// //
397 public int Z_chktrap (int deadlyTrap, int damage, Actor owner, int hittype) {
398   int res = 0;
399   Actor act;
400   //hit_xv = hit_yv = 0;
402   // check players
403   int pcount = getPlayerCount();
404   for (int pnum = 1; pnum <= pcount; ++pnum) {
405     act = getPlayerActor(pnum);
406     if (!act.isPlayer || act.isDead) continue; // this player is dead
407     if (Z_istrapped(act.x, act.y, act.radius, act.height)) {
408       ++res;
409       if (!deadlyTrap) return true;
410       if (deadlyTrap) PL_hit(act, damage, owner, hittype);
411     }
412   }
414   // check monsters
415   actorListRewind();
416   while ((act = actorListNext())) {
417     if (!act.isMonster || act.isDead) continue;
418     /+if (/*act.t??? &&*/ act.animname != MNST_DEAD)+/ {
419       if (Z_istrapped(act.x, act.y, act.radius, act.height)) {
420         ++res;
421         if (!deadlyTrap) return true;
422         if (deadlyTrap) MN_hit(act, damage, owner, hittype);
423       }
424     }
425   }
427   return res;