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