2 Copyright (C) 2004-2011 Parallel Realities
3 Copyright (C) 2011-2015 Perpendicular Dimensions
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (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.
14 See the GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 void addItem(int itemType, const char *name, int x, int y, const char *spriteName, int health, int value, int flags, bool randomMovement)
26 Entity *item = new Entity();
31 item->setSprites(graphics.getSprite(spriteName, true), graphics.getSprite(spriteName, true), graphics.getSprite(spriteName, true));
32 item->health = health;
34 item->flags = ENT_INANIMATE + ENT_BOUNCES + ENT_COLLECTABLE;
36 // raise items taller than the enemy
37 int x1 = x >> BRICKSHIFT;
38 int x2 = (x + item->width - 1) >> BRICKSHIFT;
39 int y2 = (y + item->height - 1) >> BRICKSHIFT;
40 if ((map.isSolid(x1, y2)) || (map.isSolid(x2, y2)))
42 item->y = (y2 * BRICKSIZE) - item->height;
47 item->setRandomVelocity();
50 item->health += Math::prand() % 120;
52 Math::addBit(&item->flags, flags);
54 if (item->id == ITEM_MISC_INVISIBLE)
56 if ((gameData.completedWorld) || (game.skill == 3))
58 item->id = ITEM_MISC_NOSHOW;
65 void dropBossItems(int x, int y)
67 if ((Math::prand() % 5) > 0)
72 int r = Math::rrand(ITEM_PISTOL, ITEM_DOUBLECHERRY);
74 if (player.environment == ENV_WATER)
76 r = Math::rrand(ITEM_CHERRY, ITEM_DOUBLECHERRY);
79 if ((Math::prand() % 10) == 0)
81 r = ITEM_TRIPLECHERRY;
84 addItem(defItem[r].id, defItem[r].name, x, y, defItem[r].sprite[0]->name, 240, defItem[r].value, ENT_DYING, true);
87 void dropRandomItems(int x, int y)
89 int mapX = x >> BRICKSHIFT;
90 int mapY = y >> BRICKSHIFT;
92 if (map.isSolid(mapX, mapY))
97 if (map.isBossMission)
103 int amount = Math::rrand(1, 5);
104 int r = Math::rrand(ITEM_POINTS, ITEM_POINTS7);
106 int cherryChance = 10 + (10 * game.skill);
108 for (int i = 0 ; i < amount ; i++)
110 if ((Math::prand() % 8) == 0)
112 r = Math::rrand(ITEM_PISTOL, ITEM_SPREAD);
115 if ((Math::prand() % 13) == 0)
117 switch (Math::prand() % cherryChance)
120 r = ITEM_TRIPLECHERRY;
127 r = ITEM_DOUBLECHERRY;
135 addItem(defItem[r].id, defItem[r].name, x, y, defItem[r].sprite[0]->name, 240, defItem[r].value, ENT_DYING, true);
137 r = Math::rrand(ITEM_POINTS, ITEM_POINTS7);
141 void dropHelperItems(int x, int y)
143 int amount = Math::rrand(1, 5);
146 for (int i = 0 ; i < amount ; i++)
148 r = Math::rrand(ITEM_PISTOL, ITEM_TRIPLECHERRY);
150 addItem(defItem[r].id, defItem[r].name, x, y, defItem[r].sprite[0]->name, 240, defItem[r].value, ENT_DYING, true);
156 Entity *item = (Entity*)map.itemList.getHead();
158 Objective *objective = (Objective*)map.objectiveList.getHead();
160 while (objective->next != NULL)
162 objective = (Objective*)objective->next;
163 objective->completed = true;
164 objective->currentValue = objective->targetValue;
167 while (item->next != NULL)
169 item = (Entity*)item->next;
171 if (strcmp(item->name, "Reality Crystal") == 0)
175 Math::addBit(&item->flags, ENT_TELEPORTING);
176 addTeleportParticles(item->x + (item->width / 2), item->y + (item->height / 2), 50, SND_TELEPORT3);
183 We have to do this to avoid items being permanently lost.
184 To ensure we drop them in a safe place we put them in the player's
185 last check point position...
187 void dropCarriedItems()
189 Entity *item = (Entity*)map.itemList.getHead();
191 while (item->next != NULL)
193 item = (Entity*)item->next;
195 if (item->owner != &player)
198 Math::removeBit(&item->flags, ENT_DYING);
204 item->x = game.checkPointX + Math::rrand(0, 6);
205 item->y = game.checkPointY;
206 item->flags = ENT_INANIMATE + ENT_BOUNCES + ENT_NOCOLLISIONS;
210 void pickUpItem(Entity *item)
214 if (item->flags & ENT_DYING)
216 game.totalBonusesCollected++;
218 else if (item->id >= ITEM_MISC)
220 game.currentMissionItemsCollected++;
225 item->flags = ENT_WEIGHTLESS + ENT_DYING + ENT_NOCOLLISIONS;
232 case ITEM_MACHINEGUN:
236 player.currentWeapon = &weapon[item->id];
237 game.currentWeapon = item->id;
238 audio.playSound(SND_GETWEAPON, CH_ITEM, item->x);
247 addPlayerScore(item->value);
248 audio.playSound(SND_ITEM, CH_ITEM, item->x);
251 case ITEM_DOUBLECHERRY:
252 case ITEM_TRIPLECHERRY:
253 Math::limitInt(&(player.health += item->value), 0, MAX_HEALTH);
254 audio.playSound(SND_GULP + (Math::prand() % 2), CH_ITEM, item->x);
257 item->owner = &player;
258 case ITEM_MISC_NOSHOW:
259 audio.playSound(SND_ITEM, CH_ITEM, item->x);
263 if ((item->id < ITEM_POINTS) || (item->id > ITEM_POINTS7))
266 oh yeah, right... because "Picked up a Ancient Cog" is really good English, isn't it? It's almost
267 as bad as Medal of Honor: Frontline where it said "Picked up 3 Stick Grenade(s)"... Would it really
268 have taken that much effort to pass the item number to a function that worked out some basic grammar
269 for how many items had been picked up??! Yeah... and EA expect us to pay �45 for that! Probably the
270 worst bit about that game was that it was just fecking crap anyway!
272 switch (item->name[0])
282 snprintf(string, sizeof string, _("Picked up an %s"), item->name);
285 snprintf(string, sizeof string, _("Picked up a %s"), item->name);
289 if (!map.isBossMission)
290 engine.setInfoMessage(string, 0, INFO_NORMAL);
292 checkObjectives(item->name, true);
294 if (strcmp(item->name, "LRTS") == 0)
296 presentPlayerMedal("LRTS_PART");
301 bool carryingItem(const char *name)
303 Entity *item = (Entity*)map.itemList.getHead();
305 while (item->next != NULL)
307 item = (Entity*)item->next;
309 if (item->owner != &player)
312 if (strcmp(item->name, name) == 0)
323 void showCarriedItems()
329 Entity *item = (Entity*)map.itemList.getHead();
331 while (item->next != NULL)
333 item = (Entity*)item->next;
335 if (item->owner != &player)
338 x += (item->width + 8);
344 item = (Entity*)map.itemList.getHead();
346 while (item->next != NULL)
348 item = (Entity*)item->next;
350 if (item->owner != &player)
353 graphics.blit(item->getFaceImage(), x, y, graphics.screen, false);
355 x += (item->width + 8);
359 graphics.drawString(_("Not carrying anything"), 320, 210, TXT_CENTERED, graphics.screen);
364 Entity *item = (Entity*)map.itemList.getHead();
366 while (item->next != NULL)
368 Entity *previous = item;
370 item = (Entity*)item->next;
372 if (item->id == ITEM_MISC_INVISIBLE)
377 int x = (int)(item->x - engine.playerPosX);
378 int y = (int)(item->y - engine.playerPosY);
382 if (item->flags & ENT_TELEPORTING)
386 else if ((abs(x) <= 800) && (abs(y) <= 600) && (item->owner == item))
389 if (!(item->flags & ENT_WEIGHTLESS))
390 item->applyGravity();
397 if ((item->health >= 60) || ((engine.getFrameLoop() % 3) == 0))
399 graphics.blit(item->getFaceImage(), x, y, graphics.screen, false);
404 if ((player.health > 0) && (!(player.flags & ENT_TELEPORTING)))
406 if (Collision::collision(&player, item))
408 if (item->flags & ENT_COLLECTABLE)
416 if ((item->health <= 0) && (item->owner != &player))
418 map.itemList.remove(previous, item);
426 if (!engine.loadData("data/defItems"))
427 graphics.showErrorAndExit("Couldn't load item definitions file (%s)", "data/defItems");
429 char *token = strtok((char*)engine.dataBuffer, "\n");
438 if (strcmp(token, "@EOF@") == 0)
441 sscanf(token, "%d %*c %[^\"] %*c %s %d", &id, name, sprite, &value);
444 defItem[id].setName(name);
445 defItem[id].setSprites(graphics.getSprite(sprite, true), graphics.getSprite(sprite, true), graphics.getSprite(sprite, true));
446 defItem[id].value = value;
448 token = strtok(NULL, "\n");