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 int medalWorker(void *data)
26 char *tname = (char*)data;
28 SDL_mutexP(medalServer.lock);
30 int type = medalServer.postMedal(tname);
32 while (!graphics.canShowMedalMessage())
39 if (type >= 1 && type <= 3)
41 audio.playSound(SND_ITEM, CH_ANY);
42 graphics.showMedalMessage(type, medalServer.getMessage());
44 if (medalServer.hasRuby())
46 while (!graphics.canShowMedalMessage())
53 audio.playSound(SND_ITEM, CH_ANY);
54 graphics.showMedalMessage(4, medalServer.getRubyMessage());
58 SDL_mutexV(medalServer.lock);
65 void presentPlayerMedal(const char *tname)
67 // Copy the input, so that threading
68 // doesn't trip us up!
69 char *data = new char[128];
70 strlcpy(data, tname, 128);
72 SDL_Thread *thread = SDL_CreateThread(medalWorker, "MedalWorker", (void*)data);
76 printf("Unable to create thread: %s\n", SDL_GetError());
77 printf("Calling medal server directly\n");
78 medalWorker((void*)data);
83 void addPlayerScore(int score)
85 if (game.score < 100000 && game.score + score >= 100000)
87 presentPlayerMedal("Score_100000");
89 else if (game.score < 250000 && game.score + score >= 250000)
91 presentPlayerMedal("Score_250000");
93 else if (game.score < 500000 && game.score + score >= 500000)
95 presentPlayerMedal("Score_500000");
103 game.getCheckPoint(&player.x, &player.y);
108 player.environment = ENV_AIR;
111 addTeleportParticles(player.x + 10, player.y + 10, 50, SND_TELEPORT2);
113 Math::removeBit(&player.flags, ENT_FLIES);
114 Math::removeBit(&player.flags, ENT_TELEPORTING);
115 player.setSprites(graphics.getSprite("BobRight", true), graphics.getSprite("BobLeft", true), graphics.getSprite("BobSpin", true));
118 map.windChangeTime = 90;
124 int amount = (game.gore) ? 25 : 150;
126 for (int i = 0 ; i < amount ; i++)
128 x = player.x + Math::rrand(-3, 3);
129 y = player.y + Math::rrand(-3, 3);
133 dx = Math::rrand(-5, 5);
134 dy = Math::rrand(-15, -5);
135 addEffect(x, y, dx, dy, EFF_BLEEDS);
139 dx = Math::rrand(-5, 5);
140 dy = Math::rrand(-5, 5);
141 addColoredEffect(x, y, dx, dy, graphics.yellow, EFF_COLORED + EFF_WEIGHTLESS);
145 (game.gore) ? audio.playSound(SND_SPLAT, CH_ANY) : audio.playSound(SND_POP, CH_ANY);
148 void checkPlayerBulletCollisions(Entity *bullet)
150 if ((bullet->health < 1) || (player.health <= -60))
155 if ((player.flags & ENT_TELEPORTING) || (game.missionOver > 0))
160 if (bullet->owner != &player)
162 if (Collision::collision(&player, bullet))
164 if ((!player.immune) && (!(bullet->flags & ENT_EXPLODES)))
166 addBlood(&player, bullet->dx / 4, Math::rrand(-6, -3), 1);
167 audio.playSound(SND_HIT, CH_ANY);
168 if (game.missionOverReason == MIS_INPROGRESS)
170 player.health -= bullet->damage;
175 Math::removeBit(&bullet->flags, ENT_SPARKS);
176 Math::removeBit(&bullet->flags, ENT_PUFFS);
178 if (player.health <= 0)
180 player.dx = bullet->dx;
182 audio.playSound(SND_DEATH1 + Math::prand() % 3, CH_DEATH);
186 if (bullet->id == WP_LASER)
188 debug(("Laser Hit Player"));
189 throwAndDamageEntity(&player, 0, -3, 3, -8);
201 if (engine.cheatHealth)
203 player.health = MAX_HEALTH;
206 if (game.missionOverReason == MIS_PLAYERESCAPE)
211 if (player.y > (map.limitDown + 500))
213 if (game.missionOver == 0)
218 if (player.health > 0)
220 game.setMissionOver(MIS_PLAYEROUT);
224 game.setMissionOver(MIS_PLAYERDEAD);
228 if (player.flags & ENT_TELEPORTING)
234 if (game.missionOverReason == MIS_PLAYEROUT)
236 graphics.blit(player.getFaceImage(), (int)(player.x - engine.playerPosX), (int)(player.y - engine.playerPosY), graphics.screen, false);
241 if ((player.health < 1) || (player.immune > 120))
243 if (player.health <= -60)
250 if (game.hasAquaLung)
257 graphics.blit(player.getFaceImage(), (int)(player.x - engine.playerPosX), (int)(player.y - engine.playerPosY), graphics.screen, false);
259 if (player.health < 1)
264 if (player.health <= -60)
272 if ((!(player.flags & ENT_FLIES)) && (!map.isIceLevel))
277 // toggles the Jetpack if available
278 if (config.isControl(CONTROL::JETPACK))
280 if ((game.hasJetPack) || (engine.cheatExtras))
282 if (player.flags & ENT_FLIES)
284 Math::removeBit(&player.flags, ENT_FLIES);
285 player.setSprites(graphics.getSprite("BobRight", true), graphics.getSprite("BobLeft", true), graphics.getSprite("BobSpin", true));
289 if ((player.fuel > 3) && (player.environment == ENV_AIR))
291 Math::addBit(&player.flags, ENT_FLIES);
292 player.setSprites(graphics.getSprite("JPBobRight", true), graphics.getSprite("JPBobLeft", true), graphics.getSprite("BobSpin", true));
294 else if (player.environment == ENV_WATER)
296 engine.setInfoMessage("Jetpack cannot be used underwater", 0, INFO_NORMAL);
300 engine.setInfoMessage("Jetpack is recharging...", 0, INFO_NORMAL);
306 engine.setInfoMessage("Don't have jetpack!", 0, INFO_NORMAL);
309 config.resetControl(CONTROL::JETPACK);
312 if (map.isBlizzardLevel)
314 if ((!config.isControl(CONTROL::LEFT)) && (!config.isControl(CONTROL::RIGHT)))
316 if ((player.dx > -2) && (player.dx < 2))
318 player.dx += map.windPower * 0.1;
323 if (config.isControl(CONTROL::LEFT))
327 if (player.flags & ENT_FLIES)
330 Math::limitFloat(&player.dx, -PLAYER_FLY_SPEED, PLAYER_FLY_SPEED);
332 else if (map.isIceLevel)
335 Math::limitFloat(&player.dx, -PLAYER_WALK_SPEED * 1.25, PLAYER_WALK_SPEED * 1.25);
340 player.dx = -PLAYER_WALK_SPEED;
344 if (engine.cheatSpeed)
349 else if (config.isControl(CONTROL::RIGHT))
353 if (player.flags & ENT_FLIES)
356 Math::limitFloat(&player.dx, -PLAYER_FLY_SPEED, PLAYER_FLY_SPEED);
358 else if (map.isIceLevel)
362 Math::limitFloat(&player.dx, -PLAYER_WALK_SPEED * 1.25, PLAYER_WALK_SPEED * 1.25);
366 player.dx = PLAYER_WALK_SPEED;
370 if (engine.cheatSpeed)
375 else if (!(player.flags & ENT_FLIES))
378 player.currentFrame = 0;
381 Math::limitFloat(&player.x, 10, map.limitRight + 608);
382 Math::limitFloat(&player.y, map.limitUp + 5, (MAPHEIGHT * BRICKSIZE) + 64);
384 // Keyboard break fix - Feb 09
385 if ((config.isControl(CONTROL::UP)) || (config.isControl(CONTROL::JUMP)))
387 if (player.flags & ENT_FLIES)
390 Math::limitFloat(&player.dy, -PLAYER_FLY_SPEED, PLAYER_FLY_SPEED);
391 if (engine.cheatSpeed)
396 else if ((player.environment == ENV_AIR) && (player.falling == false))
398 player.falling = true;
399 player.dy = PLAYER_JUMP_SPEED;
400 config.resetControl(CONTROL::UP);
401 config.resetControl(CONTROL::JUMP);
403 else if (player.environment != ENV_AIR)
405 player.dy = -PLAYER_WALK_SPEED;
407 if (engine.cheatSpeed)
414 if (config.isControl(CONTROL::DOWN))
416 if (player.flags & ENT_FLIES)
419 Math::limitFloat(&player.dy, -PLAYER_FLY_SPEED, PLAYER_FLY_SPEED);
421 else if (player.environment != ENV_AIR)
427 if (engine.cheatSpeed)
434 if (engine.keyState[SDL_SCANCODE_1])
435 player.currentWeapon = &weapon[WP_PISTOL];
436 else if (engine.keyState[SDL_SCANCODE_2])
437 player.currentWeapon = &weapon[WP_MACHINEGUN];
438 else if (engine.keyState[SDL_SCANCODE_3])
439 player.currentWeapon = &weapon[WP_GRENADES];
440 else if (engine.keyState[SDL_SCANCODE_4])
441 player.currentWeapon = &weapon[WP_LASER];
442 else if (engine.keyState[SDL_SCANCODE_5])
443 player.currentWeapon = &weapon[WP_SPREAD];
448 // Math::limitFloat(&player.x, 10, map.limitRight + 608);
449 // moveEntity() limits x < 10
450 if (player.x > map.limitRight + 608)
452 player.x = map.limitRight + 608;
458 // Math::limitFloat(&player.y, map.limitUp + 5, (MAPHEIGHT * BRICKSIZE) + 64);
459 if (player.y < map.limitUp + 5)
461 player.y = map.limitUp + 5;
467 else if (player.y > (MAPHEIGHT * BRICKSIZE) + 64)
469 player.y = (MAPHEIGHT * BRICKSIZE) + 64;
472 if (config.isControl(CONTROL::FIRE))
474 if (player.reload == 0)
476 addBullet(&player, player.currentWeapon->getSpeed(player.face), 0);
477 if (player.currentWeapon == &weapon[WP_SPREAD])
479 addBullet(&player, player.currentWeapon->getSpeed(player.face), 2);
480 addBullet(&player, player.currentWeapon->getSpeed(player.face), -2);
485 if (player.environment == ENV_WATER)
487 Math::removeBit(&player.flags, ENT_FLIES);
489 addBubble(player.x, player.y);
491 if ((player.thinktime == 30) && (player.oxygen == 0))
493 audio.playSound(SND_DROWNING, CH_ANY);
499 if (player.fuel == 0)
501 player.setSprites(graphics.getSprite("BobRight", true), graphics.getSprite("BobLeft", true), graphics.getSprite("BobSpin", true));
504 if ((game.hasAquaLung) || (engine.cheatExtras))
509 if (engine.cheatFuel)
514 if (((player.immune % 5) == 0) && (!(player.flags & ENT_TELEPORTING)))
516 if ((game.missionOverReason == MIS_COMPLETE) || (game.missionOverReason == MIS_INPROGRESS) || (game.missionOverReason == MIS_GAMECOMPLETE))
518 if (player.flags & ENT_FLIES)
521 addFireTrailParticle(player.x + (player.face * 16) + Math::rrand(-1, 1), player.y + 10 + Math::rrand(-1, 1));
523 graphics.blit(player.getFaceImage(), (int)(player.x - engine.playerPosX), (int)(player.y - engine.playerPosY), graphics.screen, false);