]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/player.cpp
Updated PNG icon files.
[quix0rs-blobwars.git] / src / player.cpp
1 /*
2 Copyright (C) 2004-2011 Parallel Realities
3
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.
8
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.
12
13 See the 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20
21 #include "player.h"
22
23 int medalWorker(void *data)
24 {
25         char *tname = (char*)data;
26         
27         SDL_mutexP(medalServer.lock);
28         
29         int type = medalServer.postMedal(tname);
30         
31         while (!graphics.canShowMedalMessage())
32         {
33                 SDL_Delay(100);
34         }
35         
36         SDL_Delay(100);
37         
38         if (type >= 1 && type <= 3)
39         {
40                 audio.playSound(SND_ITEM, CH_ANY);
41                 graphics.showMedalMessage(type, medalServer.getMessage());
42                 
43                 if (medalServer.hasRuby())
44                 {
45                         while (!graphics.canShowMedalMessage())
46                         {
47                                 SDL_Delay(100);
48                         }
49                         
50                         SDL_Delay(100);
51                         
52                         audio.playSound(SND_ITEM, CH_ANY);
53                         graphics.showMedalMessage(4, medalServer.getRubyMessage());
54                 }
55         }
56         
57         SDL_mutexV(medalServer.lock);
58         
59         delete[] tname;
60         
61         return type;
62 }
63
64 void presentPlayerMedal(const char *tname)
65 {
66         // Copy the input, so that threading
67         // doesn't trip us up!
68         char *data = new char[128];
69         strlcpy(data, tname, 128);
70         
71         SDL_Thread *thread = SDL_CreateThread(medalWorker, (void*)data);
72         
73         if (thread == NULL)
74         {
75                 printf("Unable to create thread: %s\n", SDL_GetError());
76                 printf("Calling medal server directly\n");
77                 medalWorker((void*)data);
78                 return;
79         }
80 }
81
82 void addPlayerScore(int score)
83 {
84         if (game.score < 100000 && game.score + score >= 100000)
85         {
86                 presentPlayerMedal("Score_100000");
87         }
88         else if (game.score < 250000 && game.score + score >= 250000)
89         {
90                 presentPlayerMedal("Score_250000");
91         }
92         else if (game.score < 500000 && game.score + score >= 500000)
93         {
94                 presentPlayerMedal("Score_500000");
95         }
96         
97         game.score += score;
98 }
99
100 void resetPlayer()
101 {
102         game.getCheckPoint(&player.x, &player.y);
103         
104         player.dx = 0;
105         player.dy = 0;
106         player.immune = 120;
107         player.environment = ENV_AIR;
108         player.oxygen = 7;
109         player.fuel = 7;
110         addTeleportParticles(player.x + 10, player.y + 10, 50, SND_TELEPORT2);
111         
112         Math::removeBit(&player.flags, ENT_FLIES);
113         Math::removeBit(&player.flags, ENT_TELEPORTING);
114         player.setSprites(graphics.getSprite("BobRight", true), graphics.getSprite("BobLeft", true), graphics.getSprite("BobSpin", true));
115         
116         map.windPower = 0;
117         map.windChangeTime = 90;
118 }
119
120 void gibPlayer()
121 {
122         float x, y, dx, dy;
123         int amount = (game.gore) ? 25 : 150;
124
125         for (int i = 0 ; i < amount ; i++)
126         {
127                 x = player.x + Math::rrand(-3, 3);
128                 y = player.y + Math::rrand(-3, 3);
129                 
130                 if (game.gore)
131                 {
132                         dx = Math::rrand(-5, 5);
133                         dy = Math::rrand(-15, -5);
134                         addEffect(x, y, dx, dy, EFF_BLEEDS);
135                 }
136                 else
137                 {
138                         dx = Math::rrand(-5, 5);
139                         dy = Math::rrand(-5, 5);
140                         addColoredEffect(x, y, dx, dy, graphics.yellow, EFF_COLORED + EFF_WEIGHTLESS);
141                 }
142         }
143
144         (game.gore) ? audio.playSound(SND_SPLAT, CH_ANY) : audio.playSound(SND_POP, CH_ANY);
145 }
146
147 void checkPlayerBulletCollisions(Entity *bullet)
148 {
149         if ((bullet->health < 1) || (player.health <= -60))
150         {
151                 return;
152         }
153
154         if ((player.flags & ENT_TELEPORTING) || (game.missionOver > 0))
155         {
156                 return;
157         }
158
159         if (bullet->owner != &player)
160         {
161                 if (Collision::collision(&player, bullet))
162                 {
163                         if ((!player.immune) && (!(bullet->flags & ENT_EXPLODES)))
164                         {
165                                 addBlood(&player, bullet->dx / 4, Math::rrand(-6, -3), 1);
166                                 audio.playSound(SND_HIT, CH_ANY);
167                                 if (game.missionOverReason == MIS_INPROGRESS)
168                                 {
169                                         player.health -= bullet->damage;
170                                         player.immune = 120;
171                                 }
172                         }
173
174                         Math::removeBit(&bullet->flags, ENT_SPARKS);
175                         Math::removeBit(&bullet->flags, ENT_PUFFS);
176
177                         if (player.health <= 0)
178                         {
179                                 player.dx = bullet->dx;
180                                 player.dy = -5;
181                                 audio.playSound(SND_DEATH1 + Math::prand() % 3, CH_DEATH);
182                                 player.health = 0;
183                         }
184
185                         if (bullet->id == WP_LASER)
186                         {
187                                 debug(("Laser Hit Player"));
188                                 throwAndDamageEntity(&player, 0, -3, 3, -8);
189                         }
190                         else
191                         {
192                                 bullet->health = 0;
193                         }
194                 }
195         }
196 }
197
198 void doPlayer()
199 {
200         if (engine.cheatHealth)
201         {
202                 player.health = MAX_HEALTH;
203         }
204
205         if (game.missionOverReason == MIS_PLAYERESCAPE)
206         {
207                 return;
208         }
209
210         if (player.y > (map.limitDown + 500))
211         {
212                 if (game.missionOver == 0)
213                 {
214                         player.health--;
215                 }
216
217                 if (player.health > 0)
218                 {
219                         game.setMissionOver(MIS_PLAYEROUT);
220                 }
221                 else
222                 {
223                         game.setMissionOver(MIS_PLAYERDEAD);
224                 }
225         }
226         
227         if (player.flags & ENT_TELEPORTING)
228         {
229                 moveEntity(&player);
230                 return;
231         }
232
233         if (game.missionOverReason == MIS_PLAYEROUT)
234         {
235                 graphics.blit(player.getFaceImage(), (int)(player.x - engine.playerPosX), (int)(player.y - engine.playerPosY), graphics.screen, false);
236                 moveEntity(&player);
237                 return;
238         }
239
240         if ((player.health < 1) || (player.immune > 120))
241         {
242                 if (player.health <= -60)
243                 {
244                         return;
245                 }
246
247                 player.think();
248                 
249                 if (game.hasAquaLung)
250                 {
251                         player.oxygen = 7;
252                 }
253
254                 moveEntity(&player);
255
256                 graphics.blit(player.getFaceImage(), (int)(player.x - engine.playerPosX), (int)(player.y - engine.playerPosY), graphics.screen, false);
257
258                 if (player.health < 1)
259                 {
260                         player.health--;
261                 }
262
263                 if (player.health <= -60)
264                 {
265                         gibPlayer();
266                 }
267
268                 return;
269         }
270
271         if ((!(player.flags & ENT_FLIES)) && (!map.isIceLevel))
272         {
273                 player.dx = 0;
274         }
275         
276         // toggles the Jetpack if available
277         if (config.isControl(CONTROL::JETPACK))
278         {
279                 if ((game.hasJetPack) || (engine.cheatExtras))
280                 {
281                         if (player.flags & ENT_FLIES)
282                         {
283                                 Math::removeBit(&player.flags, ENT_FLIES);
284                                 player.setSprites(graphics.getSprite("BobRight", true), graphics.getSprite("BobLeft", true), graphics.getSprite("BobSpin", true));
285                         }
286                         else
287                         {
288                                 if ((player.fuel > 3) && (player.environment == ENV_AIR))
289                                 {
290                                         Math::addBit(&player.flags, ENT_FLIES);
291                                         player.setSprites(graphics.getSprite("JPBobRight", true), graphics.getSprite("JPBobLeft", true), graphics.getSprite("BobSpin", true));
292                                 }
293                                 else if (player.environment == ENV_WATER)
294                                 {
295                                         engine.setInfoMessage("Jetpack cannot be used underwater", 0, INFO_NORMAL);
296                                 }
297                                 else
298                                 {
299                                         engine.setInfoMessage("Jetpack is recharging...", 0, INFO_NORMAL);
300                                 }
301                         }
302                 }
303                 else
304                 {
305                         engine.setInfoMessage("Don't have jetpack!", 0, INFO_NORMAL);
306                 }
307                 
308                 config.resetControl(CONTROL::JETPACK);
309         }
310         
311         if (map.isBlizzardLevel)
312         {
313                 if ((!config.isControl(CONTROL::LEFT)) && (!config.isControl(CONTROL::RIGHT)))
314                 {
315                         if ((player.dx > -2) && (player.dx < 2))
316                         {
317                                 player.dx += map.windPower * 0.1;
318                         }
319                 }
320         }
321
322         if (config.isControl(CONTROL::LEFT))
323         {
324                 player.face = 1;
325                 
326                 if (player.flags & ENT_FLIES)
327                 {
328                         player.dx -= 0.1;
329                         Math::limitFloat(&player.dx, -PLAYER_FLY_SPEED, PLAYER_FLY_SPEED);
330                 }
331                 else if (map.isIceLevel)
332                 {
333                         player.dx -= 0.1;
334                         Math::limitFloat(&player.dx, -PLAYER_WALK_SPEED * 1.25, PLAYER_WALK_SPEED * 1.25);
335                         player.animate();
336                 }
337                 else
338                 {
339                         player.dx = -PLAYER_WALK_SPEED;
340                         player.animate();
341                 }
342
343                 if (engine.cheatSpeed)
344                 {
345                         player.dx *= 3;
346                 }
347         }
348         else if (config.isControl(CONTROL::RIGHT))
349         {
350                 player.face = 0;
351
352                 if (player.flags & ENT_FLIES)
353                 {
354                         player.dx += 0.1;
355                         Math::limitFloat(&player.dx, -PLAYER_FLY_SPEED, PLAYER_FLY_SPEED);
356                 }
357                 else if (map.isIceLevel)
358                 {
359                         player.dx += 0.1;
360                         player.animate();
361                         Math::limitFloat(&player.dx, -PLAYER_WALK_SPEED * 1.25, PLAYER_WALK_SPEED * 1.25);
362                 }
363                 else
364                 {
365                         player.dx = PLAYER_WALK_SPEED;
366                         player.animate();
367                 }
368                 
369                 if (engine.cheatSpeed)
370                 {
371                         player.dx *= 3;
372                 }
373         }
374         else if (!(player.flags & ENT_FLIES))
375         {
376                 // usual idle frame
377                 player.currentFrame = 0;
378         }
379
380         Math::limitFloat(&player.x, 10, map.limitRight + 608);
381         Math::limitFloat(&player.y, map.limitUp + 5, (MAPHEIGHT * BRICKSIZE) + 64);
382
383         // Keyboard break fix - Feb 09
384         if ((config.isControl(CONTROL::UP)) || (config.isControl(CONTROL::JUMP)))
385         {
386                 if (player.flags & ENT_FLIES)
387                 {
388                         player.dy -= 0.1;
389                         Math::limitFloat(&player.dy, -PLAYER_FLY_SPEED, PLAYER_FLY_SPEED);
390                         if (engine.cheatSpeed)
391                         {
392                                 player.dy *= 2;
393                         }
394                 }
395                 else if ((player.environment == ENV_AIR) && (player.falling == false))
396                 {
397                         player.falling = true;
398                         player.dy = PLAYER_JUMP_SPEED;
399                         config.resetControl(CONTROL::UP);
400                         config.resetControl(CONTROL::JUMP);
401                 }
402                 else if (player.environment != ENV_AIR)
403                 {
404                         player.dy = -PLAYER_WALK_SPEED;
405                         player.animate();
406                         if (engine.cheatSpeed)
407                         {
408                                 player.dy *= 3;
409                         }
410                 }
411         }
412
413         if (config.isControl(CONTROL::DOWN))
414         {
415                 if (player.flags & ENT_FLIES)
416                 {
417                         player.dy += 0.1;
418                         Math::limitFloat(&player.dy, -PLAYER_FLY_SPEED, PLAYER_FLY_SPEED);
419                 }
420                 else if (player.environment != ENV_AIR)
421                 {
422                         player.dy = 2;
423                         player.animate();
424                 }
425
426                 if (engine.cheatSpeed)
427                 {
428                         player.dy *= 3;
429                 }
430         }
431         
432         #if DEBUG
433         if (engine.keyState[SDLK_1])
434                 player.currentWeapon = &weapon[WP_PISTOL];
435         else if (engine.keyState[SDLK_2])
436                 player.currentWeapon = &weapon[WP_MACHINEGUN];
437         else if (engine.keyState[SDLK_3])
438                 player.currentWeapon = &weapon[WP_GRENADES];
439         else if (engine.keyState[SDLK_4])
440                 player.currentWeapon = &weapon[WP_LASER];
441         else if (engine.keyState[SDLK_5])
442                 player.currentWeapon = &weapon[WP_SPREAD];
443         #endif
444         
445         moveEntity(&player);
446
447         // Math::limitFloat(&player.x, 10, map.limitRight + 608);
448         // moveEntity() limits x < 10
449         if (player.x > map.limitRight + 608)
450         {
451                 player.x = map.limitRight + 608;
452                 if (player.dx > 0)
453                 {
454                         player.dx = 0;
455                 }
456         }
457         // Math::limitFloat(&player.y, map.limitUp + 5, (MAPHEIGHT * BRICKSIZE) + 64);
458         if (player.y < map.limitUp + 5)
459         {
460                 player.y = map.limitUp + 5;
461                 if (player.dy < 0)
462                 {
463                         player.dy = 0;
464                 }
465         }
466         else if (player.y > (MAPHEIGHT * BRICKSIZE) + 64)
467         {
468                 player.y = (MAPHEIGHT * BRICKSIZE) + 64;
469         }
470
471         if (config.isControl(CONTROL::FIRE))
472         {
473                 if (player.reload == 0)
474                 {
475                         addBullet(&player, player.currentWeapon->getSpeed(player.face), 0);
476                         if (player.currentWeapon == &weapon[WP_SPREAD])
477                         {
478                                 addBullet(&player, player.currentWeapon->getSpeed(player.face), 2);
479                                 addBullet(&player, player.currentWeapon->getSpeed(player.face), -2);
480                         }
481                 }
482         }
483         
484         if (player.environment == ENV_WATER)
485         {
486                 Math::removeBit(&player.flags, ENT_FLIES);
487
488                 addBubble(player.x, player.y);
489                 
490                 if ((player.thinktime == 30) && (player.oxygen == 0))
491                 {
492                         audio.playSound(SND_DROWNING, CH_ANY);
493                 }
494         }
495
496         player.think();
497         
498         if (player.fuel == 0)
499         {
500                 player.setSprites(graphics.getSprite("BobRight", true), graphics.getSprite("BobLeft", true), graphics.getSprite("BobSpin", true));
501         }
502         
503         if ((game.hasAquaLung) || (engine.cheatExtras))
504         {
505                 player.oxygen = 7;
506         }
507                 
508         if (engine.cheatFuel)
509         {
510                 player.fuel = 7;
511         }
512
513         if (((player.immune % 5) == 0) && (!(player.flags & ENT_TELEPORTING)))
514         {
515                 if ((game.missionOverReason == MIS_COMPLETE) || (game.missionOverReason == MIS_INPROGRESS) || (game.missionOverReason == MIS_GAMECOMPLETE))
516                 {
517                         if (player.flags & ENT_FLIES)
518                         {
519                                 player.animate();
520                                 addFireTrailParticle(player.x + (player.face * 16) + Math::rrand(-1, 1), player.y + 10 + Math::rrand(-1, 1));
521                         }
522                         graphics.blit(player.getFaceImage(), (int)(player.x - engine.playerPosX), (int)(player.y - engine.playerPosY), graphics.screen, false);
523                 }
524         }
525 }