2 Copyright (C) 2004-2011 Parallel Realities
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * Opens a door and converts it into a normal door (TR_DOOR)
25 * at the same time. Uses up keys if needed
26 * @param train The door to open.
28 void openDoor(Train *train)
38 case TR_GOLD_SLIDEDOOR:
39 engine.setInfoMessage("Used Gold Key", 1, INFO_NORMAL);
42 case TR_SILVER_SLIDEDOOR:
43 engine.setInfoMessage("Used Silver Key", 1, INFO_NORMAL);
46 case TR_BRONZE_SLIDEDOOR:
47 engine.setInfoMessage("Used Bronze Key", 1, INFO_NORMAL);
51 if ((train->type != TR_LOCKED_DOOR) && (train->type != TR_LOCKED_SLIDEDOOR))
53 if (train->type < TR_SLIDEDOOR)
55 train->type = TR_DOOR;
59 train->type = TR_SLIDEDOOR;
65 audio.playSound(SND_OPENDOOR, CH_TOUCH);
69 * Blocks an entity from moving any further and shows
70 * a message for the reason the door would not open
71 * @param ent The entity to block
72 * @param message The message to show when blocking the Player
73 * @param train The door that performs the blocking
74 * @param dir The direction the entity was moving in (required for clipping)
76 void trainBlockEntity(Entity *ent, const char *message, Train *train, int dir)
80 if ((train->isReady()) && (!train->active))
82 engine.setInfoMessage(message, 1, INFO_NORMAL);
83 audio.playSound(SND_LOCKEDDOOR, CH_TOUCH);
87 if ((ent->flags & ENT_BULLET) && (!(ent->flags & ENT_BOUNCES)))
91 if (ent->dx < 0) ent->x = train->x + train->sprite->image[0]->w;
92 if (ent->dx > 0) ent->x = train->x - ent->width;
98 if ((ent->dy >= 0) && (train->type >= TR_SLIDEDOOR))
101 ent->falling = false;
107 * Checks to see if an entity has touched this train. Depending on
108 * the trains status certain other functions will be invoked
109 * @param ent The entity to test
110 * @param dir The direction the entity was moving in
111 * @return Whether a collision took place
113 bool checkTrainContact(Entity *ent, int dir)
115 Train *train = (Train*)map.trainList.getHead();
117 bool collision = false;
118 int x, y, mapAttribute;
120 while (train->next != NULL)
122 train = (Train*)train->next;
126 collision = (Collision::collision(ent->x + ent->dx, ent->y, ent->width, ent->height - 1, train->x, train->y, train->width, train->height));
130 collision = (Collision::collision(ent->x, ent->y + ent->dy, ent->width, ent->height - 1, train->x, train->y, train->width, train->height));
138 if (ent->flags & ENT_BULLET)
143 if (ent->flags & ENT_FLIES)
148 if ((ent == &player) && (train->waitsForPlayer()))
150 train->active = true;
153 x = (int)(ent->x + ent->dx) >> BRICKSHIFT;
154 y = (int)(ent->y + ent->height - 1) >> BRICKSHIFT;
156 mapAttribute = map.data[x][y];
158 evaluateMapAttribute(ent, mapAttribute);
166 ent->x -= train->getDX();
173 ent->y -= ent->height;
175 ent->falling = false;
182 if (!(ent->flags & ENT_BULLET))
190 ent->falling = false;
196 case TR_LOCKED_SLIDEDOOR:
197 trainBlockEntity(ent, "Door is locked", train, dir);
202 case TR_GOLD_SLIDEDOOR:
203 if ((ent == &player) && (carryingItem("Gold Key")))
209 trainBlockEntity(ent, "Gold Key Required", train, dir);
215 case TR_SILVER_SLIDEDOOR:
216 if ((ent == &player) && (carryingItem("Silver Key")))
222 trainBlockEntity(ent, "Silver Key Required", train, dir);
228 case TR_BRONZE_SLIDEDOOR:
229 if ((ent == &player) && (carryingItem("Bronze Key")))
235 trainBlockEntity(ent, "Bronze Key Required", train, dir);
247 * Lazy way of setting the sprite for the train
248 * @param train The train to set the Sprite for
250 void setTrainSprite(Train *train)
255 train->sprite = graphics.getSprite("Platform", true);
259 train->sprite = graphics.getSprite("NormalDoor", true);
262 train->sprite = graphics.getSprite("GoldDoor", true);
265 train->sprite = graphics.getSprite("SilverDoor", true);
268 train->sprite = graphics.getSprite("BronzeDoor", true);
271 case TR_LOCKED_SLIDEDOOR:
272 train->sprite = graphics.getSprite("SlideDoor", true);
274 case TR_GOLD_SLIDEDOOR:
275 train->sprite = graphics.getSprite("GoldSlideDoor", true);
277 case TR_SILVER_SLIDEDOOR:
278 train->sprite = graphics.getSprite("SilverSlideDoor", true);
280 case TR_BRONZE_SLIDEDOOR:
281 train->sprite = graphics.getSprite("BronzeSlideDoor", true);
287 * Checks to see if a door has attempted to open or close on the Player
289 * @param train The door to perform the check on
290 * @return Whether an entity was in the path of the door
292 bool doorClosedOnEntity(Train *train)
294 // allow entities to stand on an horizontal moving door without blocking its movement.
295 int y = (train->type < TR_SLIDEDOOR) ? (int)train->y : (int)train->y + 1;
297 if (Collision::collision(player.x, player.y, player.width, player.height, train->x, y, train->width, train->height))
302 Entity *enemy = (Entity*)map.enemyList.getHead();
304 while (enemy->next != NULL)
306 enemy = (Entity*)enemy->next;
308 if (Collision::collision(enemy->x, enemy->y, enemy->width, enemy->height, train->x, y, train->width, train->height))
318 * Peforms actions for all the trains on the level. Moves them, etc.
322 Train *train = (Train*)map.trainList.getHead();
324 int x, y, oldX, oldY;
325 int playSound = false;
327 while (train->next != NULL)
329 train = (Train*)train->next;
331 x = (int)(train->x - engine.playerPosX);
332 y = (int)(train->y - engine.playerPosY);
334 if ((train->type == TR_TRAIN) && (train->active))
339 if (train->type != TR_TRAIN)
341 oldX = (int)train->x;
342 oldY = (int)train->y;
345 playSound = train->openClose();
347 // only check if the door actually moved(!)
348 if ((oldX != (int)train->x) || (oldY != (int)train->y))
350 if (doorClosedOnEntity(train))
357 audio.playSound(SND_DOOROPENED, CH_TOUCH);
362 if (train->sprite == NULL)
364 setTrainSprite(train);
367 if ((abs(x) <= 800) && (abs(y) <= 600))
369 graphics.blit(train->sprite->getCurrentFrame(), x, y, graphics.screen, false);