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.
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.
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.
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/>.
26 public const SW_PL_PRESS = BIT(0);
27 public const SW_MN_PRESS = BIT(1);
28 public const SW_PL_NEAR = BIT(2);
29 public const SW_MN_NEAR = BIT(3);
30 public const SW_KEY_R = BIT(4);
31 public const SW_KEY_G = BIT(5);
32 public const SW_KEY_B = BIT(6);
35 public int switchGetD (Actor me) { return (me.switchabf>>24)&0xff; }
36 public void switchSetD (Actor me, int d) { me.switchabf = (me.switchabf&0x00ffffffU)|((d&0xff)<<24); }
37 public int switchGetA (Actor me) { return (me.switchabf>>16)&0xff; }
38 public int switchGetB (Actor me) { return (me.switchabf>>8)&0xff; }
39 public int switchGetFlags (Actor me) { return (me.switchabf&0xff); }
42 // `pressed`==false: proximity
43 public auto switchTouch (Actor me, Actor other, int pressed) {
44 if (me.dead || other.dead) return false;
46 int x = other.x, y = other.y;
47 int sx = (x-other.radius)/TileSize;
48 int sy = (y-other.height+1)/TileSize;
49 x = (x+other.radius)/TileSize;
52 int myx = me.x/TileSize;
53 int myy = me.y/TileSize;
55 if (other.classname == "DummyPressActor") writeln("sx=", sx, "; sy=", sy, "; x=", x, "; y=", y, "; myx=", myx, "; myy=", myy);
57 if (myx >= sx && myx <= x && myy >= sy && myy <= y) {
58 if (other.classname == "DummyPressActor") {
59 if (other.atm == 1) writeln("*** PRESSACTOR ACTIVATED SWITCH ***");
60 return (other.atm == 1);
62 auto sflags = me.switchGetFlags();
63 //if (other.isPlayer) writeln("isPlayer:", other.isPlayer, "; PLP:", (sflags&SW_PL_PRESS), "; PLN:", (sflags&SW_MN_NEAR));
66 if (((sflags&SW_PL_PRESS) && other.isPlayer) ||
67 ((sflags&SW_MN_PRESS) && other.isMonster)) return true;
70 if (((sflags&SW_PL_NEAR) && other.isPlayer) ||
71 ((sflags&SW_MN_NEAR) && other.isMonster)) return true;
77 public Actor switchWhoTouched (Actor me) {
78 if (me.dead) return null;
80 for (Actor other = getNextTouchListItem; other; other = getNextTouchListItem) {
81 //writeln("switch touch: '", other.classtype, ":", other.classname, "'");
82 if (other.dead) continue;
83 if (!other.isPlayer && !other.isMonster && other.classname != "DummyPressActor") continue;
84 if (other.classname == "DummyPressActor") writeln("DUMMYACTOR CHECK");
87 auto btn = getPlayerButtons(other.plrnum);
88 press = ((btn&PLK_USE) != 0);
90 if (!me.switchTouch(other, press)) {
91 if (other.classname == "DummyPressActor") writeln("DUMMYACTOR FUCK");
94 if (other.classname == "DummyPressActor") writeln("DUMMYACTOR OK");
95 //writeln(" switch: real touch");
97 auto sflags = me.switchGetFlags();
98 if ((sflags&SW_KEY_R) && !other.hasRedKey) continue;
99 if ((sflags&SW_KEY_G) && !other.hasGreenKey) continue;
100 if ((sflags&SW_KEY_B) && !other.hasBlueKey) continue;
103 return null; // invalid actor
107 public void switchOpenDoor (Actor me) {
108 if (me.dead) return null;
109 int a = me.switchGetA();
110 int b = me.switchGetB();
112 //swsnd = Z_sound(sndbdo, 128);
113 auto j = mapGetTile(LAYER_FRONT, a, b);
118 processDoor(a, b, TILE_DOORC, TILE_DOORO, 0, true);
119 mapSetTile(LAYER_FRONT, a, b, j);
123 public int switchShutDoor (Actor me) {
124 if (me.dead) return false;
125 int a = me.switchGetA();
126 int b = me.switchGetB();
127 //int cht = TILE_DOORO;
128 //int chto = TILE_ACTTRAP;
129 int chf = mapGetTile(LAYER_FRONT, a, b);
131 processDoor(a, b, TILE_DOORO, TILE_ACTTRAP, chf, true);
132 //cht = TILE_ACTTRAP;
133 if (Z_chktrap(false, 0, null, HIT_SOME)) {
134 int j = mapGetTile(LAYER_FRONT, a, b);
138 processDoor(a, b, TILE_ACTTRAP, TILE_DOORO, 0, true);
139 mapSetTile(LAYER_FRONT, a, b, j);
143 processDoor(a, b, TILE_ACTTRAP, TILE_DOORC, chf, true);
144 //swsnd = Z_sound(sndbdc, 128);
149 public int switchShutTrap (Actor me) {
150 if (me.dead) return false;
151 int a = me.switchGetA();
152 int b = me.switchGetB();
153 if (mapGetTypeTile(a, b) != TILE_DOORO) return false;
155 //chto = TILE_ACTTRAP;
156 int chf = mapGetTile(LAYER_FRONT, a, b);
158 processDoor(a, b, TILE_DOORO, TILE_ACTTRAP, chf, true);
159 Z_chktrap(true, 100, null, HIT_TRAP);
160 //cht = TILE_ACTTRAP;
162 processDoor(a, b, TILE_ACTTRAP, TILE_DOORC|0x80, chf, true);
163 //swsnd = Z_sound(sndswn, 128);
170 public const SW_LIFT_TOGGLE = 0;
171 public const SW_LIFT_UP = 1;
172 public const SW_LIFT_DOWN = 2;
174 public void switchLift (Actor me, int type/*SW_LIFT_XXX*/) {
175 if (me.dead) return false;
176 int a = me.switchGetA();
177 int b = me.switchGetB();
179 if (type == SW_LIFT_TOGGLE) {
180 switch (mapGetTypeTile(a, b)) {
181 case TILE_LIFTD: type = SW_LIFT_UP; break;
182 case TILE_LIFTU: type = SW_LIFT_DOWN; break;
186 if (type == SW_LIFT_UP) {
193 if (mapGetTypeTile(a, b) != cht) return;
194 processDoor(a, b, cht, chto, 0, false);
195 //swsnd = Z_sound(sndswx, 128);
196 me.atm = 9; // cooldown time
200 // `x` and `y` in tiles
201 void processDoor (int x, int y, int cht, int chto, int chf, int f_ch) {
202 if (x < 0 || y < 0 || x >= MapWidth || y >= MapHeight) return;
203 if (mapGetTypeTile(x, y) != cht) return;
205 for (; x && mapGetTypeTile(x-1, y) == cht; --x) {}
206 for (; ex < MapWidth && mapGetTypeTile(ex, y) == cht; ++ex) {}
207 for (int mx = x; mx < ex; ++mx) mapSetTypeTile(mx, y, chto); //memset(fldm+y*MapWidth+x, chto, ex-x);
208 if (f_ch) for (int mx = x; mx < ex; ++mx) mapSetTile(LAYER_FRONT, mx, y, chf); //if (f_ch) memset(fldf+y*MapWidth+x, chf, ex-x);
209 for (; x < ex; ++x) {
210 processDoor(x, y-1, cht, chto, chf, f_ch);
211 processDoor(x, y+1, cht, chto, chf, f_ch);
216 // ////////////////////////////////////////////////////////////////////////// //
217 //public const SwitchSkipAction = -666;
218 //int funcdummy (Actor me) { return 0; }
219 //public int switchThink (Actor me) { return me.switchThink(&funcdummy); }
220 public void switchThink (Actor me, void function (Actor me) actcb) {
225 me.atm = 0; // just in case
231 public void switchTrapCooldown (Actor me) {
233 int d = me.switchGetD();
235 int a = me.switchGetA();
236 int b = me.switchGetB();
237 if (mapGetTypeTile(a, b) != TILE_DOORC) {
249 public void switchDoorCloseCooldown (Actor me) {
251 int d = me.switchGetD();
253 int a = me.switchGetA();
254 int b = me.switchGetB();
255 if (mapGetTypeTile(a, b) != TILE_DOORO) {
259 if (--d == 0 && !me.switchShutDoor) d = 9;
264 public void switchToggleDoor (Actor me) {
266 int a = me.switchGetA();
267 int b = me.switchGetB();
268 switch (mapGetTypeTile(a, b)) {
271 me.atm = 9; // cooldown time
272 me.switchSetD(me.classname == "Door5" ? 90 : 0);
275 if (me.switchShutDoor) {
276 me.atm = 9; // cooldown time
279 //if (!swsnd) swsnd = Z_sound(sndnoway, 128);