1 /*-------------------------------------------------------------------------------
2
3 BARONY
4 File: drawminimap.cpp
5 Desc: contains drawMinimap()
6
7 Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 See LICENSE for details.
9
10 -------------------------------------------------------------------------------*/
11
12 #include "../main.hpp"
13 #include "../draw.hpp"
14 #include "../game.hpp"
15 #include "../stat.hpp"
16 #include "../items.hpp"
17 #include "../sound.hpp"
18 #include "../menu.hpp"
19 #include "../player.hpp"
20 #include "interface.hpp"
21 #include "../collision.hpp"
22 #include "../mod_tools.hpp"
23
24 /*-------------------------------------------------------------------------------
25
26 drawMinimap
27
28 Draws the game's minimap in the lower right corner of the screen
29
30 -------------------------------------------------------------------------------*/
31
32 Uint32 minotaur_timer = 0;
33 std::vector<MinimapPing> minimapPings;
34 int minimapPingGimpTimer = -1;
35 Uint32 lastMapTick = 0;
36
minimapColorFunc(Uint8 r,Uint8 g,Uint8 b,Uint8 a)37 Uint32 minimapColorFunc(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
38 Uint32 result = 0u;
39 result |= (Uint32)a << 24;
40 result |= (Uint32)b << 16;
41 result |= (Uint32)g << 8;
42 result |= (Uint32)r;
43 return result;
44 }
45
drawMinimap()46 void drawMinimap()
47 {
48 if ( gameplayCustomManager.inUse() )
49 {
50 if ( CustomHelpers::isLevelPartOfSet(currentlevel, secretlevel, gameplayCustomManager.minimapDisableFloors) )
51 {
52 return;
53 }
54 }
55
56 node_t* node;
57 Uint32 color;
58 int x, y, i;
59 int minimapTotalScale = minimapScaleQuickToggle + minimapScale;
60 // handle toggling scale hotkey.
61 if ( !command && *inputPressed(impulses[IN_MINIMAPSCALE]) || (shootmode && *inputPressed(joyimpulses[INJOY_GAME_MINIMAPSCALE])) )
62 {
63 if ( minimapScaleQuickToggle == 3 )
64 {
65 minimapScaleQuickToggle = 0;
66 }
67 else
68 {
69 ++minimapScaleQuickToggle;
70 }
71 *inputPressed(impulses[IN_MINIMAPSCALE]) = 0;
72 *inputPressed(joyimpulses[INJOY_GAME_MINIMAPSCALE]) = 0;
73 playSound(139, 32);
74 }
75
76 if ( map.height > 64 || map.width > 64 )
77 {
78 int maxDimension = std::max(map.height, map.width);
79 maxDimension -= 64;
80 int numMinimapSizesToReduce = 0;
81 while ( maxDimension > 0 )
82 {
83 maxDimension -= 32;
84 ++numMinimapSizesToReduce;
85 }
86 minimapTotalScale = std::max(1, minimapScale - numMinimapSizesToReduce) + minimapScaleQuickToggle;
87 }
88
89 // create a new minimap texture
90 SDL_Surface* minimapSurface = SDL_CreateRGBSurface(0, map.width, map.height, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
91 TempTexture* minimapTexture = new TempTexture();
92 SDL_LockSurface(minimapSurface);
93
94 // draw level
95 glDisable(GL_DEPTH_TEST);
96 glDisable(GL_LIGHTING);
97 glMatrixMode(GL_PROJECTION);
98 glViewport(0, 0, xres, yres);
99 glLoadIdentity();
100 glOrtho(0, xres, 0, yres, -1, 1);
101 glMatrixMode(GL_MODELVIEW);
102 for ( x = 0; x < map.width; x++ )
103 {
104 for ( y = 0; y < map.height; y++ )
105 {
106 Uint32 color = 0;
107 if ( minimap[y][x] == 0 )
108 {
109 color = minimapColorFunc(32, 12, 0, 255 * ((100 - minimapTransparencyBackground) / 100.f));
110 }
111 else if ( minimap[y][x] == 1 )
112 {
113 color = minimapColorFunc(96, 24, 0, 255 * ((100 - minimapTransparencyForeground) / 100.f));
114 }
115 else if ( minimap[y][x] == 2 )
116 {
117 color = minimapColorFunc(192, 64, 0, 255 * ((100 - minimapTransparencyForeground) / 100.f));
118 }
119 else if ( minimap[y][x] == 3 )
120 {
121 color = minimapColorFunc(32, 32, 32, 255 * ((100 - minimapTransparencyForeground) / 100.f));
122 }
123 else if ( minimap[y][x] == 4 )
124 {
125 color = minimapColorFunc(64, 64, 64, 255 * ((100 - minimapTransparencyForeground) / 100.f));
126 }
127 putPixel(minimapSurface, x, y, color);
128 }
129 }
130 SDL_UnlockSurface(minimapSurface);
131 minimapTexture->load(minimapSurface, false, true);
132 minimapTexture->bind();
133 glColor4f(1, 1, 1, 1);
134 glBegin(GL_QUADS);
135 glTexCoord2f(0, 0);
136 glVertex2f(xres - map.width * minimapTotalScale, map.height * minimapTotalScale);
137 glTexCoord2f(0, 1);
138 glVertex2f(xres - map.width * minimapTotalScale, 0);
139 glTexCoord2f(1, 1);
140 glVertex2f(xres, 0);
141 glTexCoord2f(1, 0);
142 glVertex2f(xres, map.height * minimapTotalScale);
143 glEnd();
144 glBindTexture(GL_TEXTURE_2D, 0);
145 if (minimapTexture) {
146 delete minimapTexture;
147 minimapTexture = nullptr;
148 }
149 if (minimapSurface) {
150 SDL_FreeSurface(minimapSurface);
151 minimapSurface = nullptr;
152 }
153 glDisable(GL_DEPTH_TEST);
154 glDisable(GL_LIGHTING);
155 glMatrixMode(GL_PROJECTION);
156 glViewport(0, 0, xres, yres);
157 glLoadIdentity();
158 glOrtho(0, xres, 0, yres, -1, 1);
159 glMatrixMode(GL_MODELVIEW);
160 glBindTexture(GL_TEXTURE_2D, 0);
161
162 // draw exits/monsters
163 glBegin(GL_QUADS);
164 for ( node = map.entities->first; node != NULL; node = node->next )
165 {
166 Entity* entity = (Entity*)node->element;
167 if ( entity->sprite == 161 || (entity->sprite >= 254 && entity->sprite < 258)
168 || entity->behavior == &actCustomPortal ) // ladder or portal models
169 {
170 if ( entity->x >= 0 && entity->y >= 0 && entity->x < map.width << 4 && entity->y < map.height << 4 )
171 {
172 x = floor(entity->x / 16);
173 y = floor(entity->y / 16);
174 if ( minimap[y][x] || (entity->entityShowOnMap > 0 && !(entity->behavior == &actCustomPortal)) )
175 {
176 if ( ticks % 40 - ticks % 20 )
177 {
178 glColor4f( 0, 1, 1, 1 );
179 //glBegin(GL_QUADS);
180 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
181 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
182 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
183 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
184 //glEnd();
185 }
186 }
187 }
188 }
189 else
190 {
191 if ( entity->skill[28] > 0 ) // mechanism
192 {
193 if ( entity->behavior == &actCustomPortal
194 || entity->behavior == &actTextSource
195 || entity->behavior == &actFloorDecoration )
196 {
197 continue;
198 }
199 }
200 if ( entity->behavior == &actMonster && entity->monsterAllyIndex < 0 )
201 {
202 bool warningEffect = false;
203 if ( (players[clientnum] && players[clientnum]->entity
204 && players[clientnum]->entity->creatureShadowTaggedThisUid == entity->getUID())
205 || (entity->getStats() && entity->getStats()->EFFECTS[EFF_SHADOW_TAGGED]) )
206 {
207 warningEffect = true;
208 x = floor(entity->x / 16);
209 y = floor(entity->y / 16);
210 glColor4f(.75, .75, .75, 1);
211 //glBegin(GL_QUADS);
212 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
213 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
214 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
215 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
216 //glEnd();
217 }
218 if ( !warningEffect
219 && ((stats[clientnum]->ring && stats[clientnum]->ring->type == RING_WARNING)
220 || (entity->entityShowOnMap > 0)) )
221 {
222 int beatitude = 0;
223 if ( stats[clientnum]->ring && stats[clientnum]->ring->type == RING_WARNING )
224 {
225 beatitude = stats[clientnum]->ring->beatitude;
226 // invert for succ/incubus
227 if ( beatitude < 0 && shouldInvertEquipmentBeatitude(stats[clientnum]) )
228 {
229 beatitude = abs(stats[clientnum]->ring->beatitude);
230 }
231 }
232
233 bool doEffect = false;
234 if ( entity->entityShowOnMap > 0 )
235 {
236 doEffect = true;
237 }
238 else if ( stats[clientnum]->ring && players[clientnum] && players[clientnum]->entity
239 && entityDist(players[clientnum]->entity, entity) < 16.0 * std::max(3, (11 + 5 * beatitude)) )
240 {
241 doEffect = true;
242 }
243 if ( doEffect )
244 {
245 x = floor(entity->x / 16);
246 y = floor(entity->y / 16);
247 glColor4f(0.75, 0.5, 0.75, 1);
248 //glBegin(GL_QUADS);
249 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
250 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
251 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
252 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
253 //glEnd();
254 warningEffect = true;
255 }
256 }
257 if ( !warningEffect && stats[clientnum]->shoes != NULL )
258 {
259 if ( stats[clientnum]->shoes->type == ARTIFACT_BOOTS )
260 {
261 if ( (abs(entity->vel_x) > 0.1 || abs(entity->vel_y) > 0.1)
262 && players[clientnum] && players[clientnum]->entity
263 && entityDist(players[clientnum]->entity, entity) < 16.0 * 20 )
264 {
265 entity->entityShowOnMap = std::max(entity->entityShowOnMap, TICKS_PER_SECOND * 5);
266 x = floor(entity->x / 16);
267 y = floor(entity->y / 16);
268 glColor4f(0.75, 0.5, 0.75, 1);
269 //glBegin(GL_QUADS);
270 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
271 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
272 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
273 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
274 //glEnd();
275 }
276 }
277 }
278 }
279 else if ( entity->isBoulderSprite() ) // boulder.vox
280 {
281 x = std::min<int>(std::max<int>(0, entity->x / 16), map.width - 1);
282 y = std::min<int>(std::max<int>(0, entity->y / 16), map.height - 1);
283 if ( minimap[y][x] == 1 || minimap[y][x] == 2 )
284 {
285 glColor4f( 192 / 255.f, 64 / 255.f, 0 / 255.f, 1 );
286 //glBegin(GL_QUADS);
287 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
288 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
289 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
290 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
291 //glEnd();
292 }
293 }
294 else if ( entity->behavior == &actItem && entity->itemShowOnMap == 1 )
295 {
296 x = floor(entity->x / 16);
297 y = floor(entity->y / 16);
298 if ( ticks % 40 - ticks % 20 )
299 {
300 glColor4f(240 / 255.f, 228 / 255.f, 66 / 255.f, 1); // yellow
301 //glBegin(GL_QUADS);
302 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
303 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
304 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
305 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
306 }
307 }
308 else if ( entity->entityShowOnMap > 0 )
309 {
310 x = floor(entity->x / 16);
311 y = floor(entity->y / 16);
312 if ( ticks % 40 - ticks % 20 )
313 {
314 glColor4f(255 / 255.f, 168 / 255.f, 200 / 255.f, 1); // pink
315 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
316 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale - minimapTotalScale);
317 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale + minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
318 glVertex2f(x * minimapTotalScale + xres - map.width * minimapTotalScale, map.height * minimapTotalScale - y * minimapTotalScale);
319 }
320 }
321 }
322 if ( entity->entityShowOnMap > 0 && lastMapTick != ticks )
323 {
324 // only decrease the entities' shown duration when the global game timer passes a tick
325 // (drawMinimap doesn't follow game tick intervals)
326 --entity->entityShowOnMap;
327 }
328 }
329 lastMapTick = ticks;
330 glEnd();
331
332 // draw player pings
333 if ( !minimapPings.empty() )
334 {
335 for ( std::vector<MinimapPing>::iterator it = minimapPings.begin(); it != minimapPings.end();)
336 {
337 MinimapPing ping = *it;
338 switch ( ping.player )
339 {
340 case 0:
341 color = SDL_MapRGB(mainsurface->format, 64, 255, 64); // green
342 break;
343 case 1:
344 color = SDL_MapRGB(mainsurface->format, 86, 180, 233); // sky blue
345 break;
346 case 2:
347 color = SDL_MapRGB(mainsurface->format, 240, 228, 66); // yellow
348 break;
349 case 3:
350 color = SDL_MapRGB(mainsurface->format, 204, 121, 167); // pink
351 break;
352 default:
353 color = SDL_MapRGB(mainsurface->format, 192, 192, 192); // grey
354 break;
355 }
356
357 int aliveTime = ticks - ping.tickStart;
358 if ( aliveTime < TICKS_PER_SECOND * 2.5 ) // 2.5 second duration.
359 {
360 if ( (aliveTime < TICKS_PER_SECOND && (aliveTime % 10 < 5)) || aliveTime >= TICKS_PER_SECOND || ping.radiusPing )
361 {
362 // draw the ping blinking every 5 ticks if less than 1 second lifetime, otherwise constantly draw.
363 x = xres - map.width * minimapTotalScale + ping.x * minimapTotalScale;
364 y = yres - map.height * minimapTotalScale + ping.y * minimapTotalScale;
365 int alpha = 255;
366 if ( ping.radiusPing )
367 {
368 alpha = 50;
369 }
370 if ( aliveTime >= TICKS_PER_SECOND * 2 )
371 {
372 // start fading ping after 2 seconds, lasting 0.5 seconds.
373 real_t alphafade = 1 - (aliveTime - TICKS_PER_SECOND * 2) / static_cast<real_t>(TICKS_PER_SECOND * 0.5);
374 alpha = std::max(static_cast<int>(alphafade * alpha), 0);
375 }
376 // draw a circle
377 if ( ping.radiusPing )
378 {
379 int radius = 3 + std::min(30, aliveTime);
380 radius = std::min(minimapTotalScale * 6, radius);
381 drawCircle(x - 1, y - 1, std::max(radius + minimapObjectZoom, 0), color, alpha);
382 }
383 else
384 {
385 drawCircle(x - 1, y - 1, std::max(3 + minimapObjectZoom, 0), color, alpha);
386 }
387 }
388 }
389
390
391 // prune old pings > 2.5 seconds
392 if ( aliveTime > TICKS_PER_SECOND * 2.5 )
393 {
394 if ( ping.player == clientnum )
395 {
396 if ( minimapPingGimpTimer > TICKS_PER_SECOND / 4 )
397 {
398 minimapPingGimpTimer = TICKS_PER_SECOND / 4; // reduce the gimp timer when one of the player's own pings fades.
399 }
400 }
401 it = minimapPings.erase(it);
402 }
403 else
404 {
405 ++it;
406 }
407 }
408 }
409
410 // draw players and allies
411
412 for ( node = map.creatures->first; node != nullptr; node = node->next )
413 {
414 Entity* entity = (Entity*)node->element;
415 int drawMonsterAlly = -1;
416 int foundplayer = -1;
417 if ( entity->behavior == &actPlayer )
418 {
419 foundplayer = entity->skill[2];
420 }
421 else if ( entity->behavior == &actMonster )
422 {
423 if ( entity->monsterAllyIndex >= 0 )
424 {
425 drawMonsterAlly = entity->monsterAllyIndex;
426 }
427 }
428 if ( drawMonsterAlly >= 0 || foundplayer >= 0 )
429 {
430 // my player = green, other players = blue
431 if ( foundplayer >= 0 )
432 {
433 switch ( foundplayer )
434 {
435 case 0:
436 color = SDL_MapRGB(mainsurface->format, 64, 255, 64); // green
437 break;
438 case 1:
439 color = SDL_MapRGB(mainsurface->format, 86, 180, 233); // sky blue
440 break;
441 case 2:
442 color = SDL_MapRGB(mainsurface->format, 240, 228, 66); // yellow
443 break;
444 case 3:
445 color = SDL_MapRGB(mainsurface->format, 204, 121, 167); // pink
446 break;
447 default:
448 color = SDL_MapRGB(mainsurface->format, 192, 192, 192); // grey
449 break;
450 }
451 if ( players[clientnum] && players[clientnum]->entity
452 && players[clientnum]->entity->creatureShadowTaggedThisUid == entity->getUID() )
453 {
454 color = SDL_MapRGB(mainsurface->format, 192, 192, 192); // grey
455 }
456 //color = SDL_MapRGB(mainsurface->format, 0, 192, 0);
457 }
458 else
459 {
460 switch ( drawMonsterAlly )
461 {
462 case 0:
463 color = SDL_MapRGB(mainsurface->format, 64, 255, 64); // green
464 break;
465 case 1:
466 color = SDL_MapRGB(mainsurface->format, 86, 180, 233); // sky blue
467 break;
468 case 2:
469 color = SDL_MapRGB(mainsurface->format, 240, 228, 66); // yellow
470 break;
471 case 3:
472 color = SDL_MapRGB(mainsurface->format, 204, 121, 167); // pink
473 break;
474 default:
475 color = SDL_MapRGB(mainsurface->format, 192, 192, 192); // grey
476 break;
477 }
478 if ( players[clientnum] && players[clientnum]->entity
479 && players[clientnum]->entity->creatureShadowTaggedThisUid == entity->getUID() )
480 {
481 color = SDL_MapRGB(mainsurface->format, 192, 192, 192); // grey
482 }
483 }
484
485 // draw the first pixel
486 x = xres - map.width * minimapTotalScale + (int)(entity->x / (16.f / minimapTotalScale));
487 y = map.height * minimapTotalScale - (int)(entity->y / (16.f / minimapTotalScale));
488 if ( foundplayer >= 0 )
489 {
490 if ( softwaremode )
491 {
492 //SPG_Pixel(screen,(int)(players[c]->x/16)+564+x+xres/2-(status_bmp->w/2),(int)(players[c]->y/16)+yres-71+y,color); //TODO: NOT a PLAYERSWAP
493 }
494 else
495 {
496 glColor4f(((Uint8)(color >> mainsurface->format->Rshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Gshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Bshift)) / 255.f, 1);
497 glBegin(GL_POINTS);
498 glVertex2f( x, y );
499 glEnd();
500 }
501 }
502
503 // draw a circle
504 if ( foundplayer >= 0 )
505 {
506 drawCircle(x - 1, yres - y - 1, std::max(3 + minimapObjectZoom, 0), color, 255);
507 }
508 else
509 {
510 drawCircle(x - 1, yres - y - 1, std::max(2 + minimapObjectZoom, 0), color, 128);
511 }
512
513 x = 0;
514 y = 0;
515 if ( foundplayer >= 0 )
516 {
517 for ( i = 0; i < 4 + minimapObjectZoom; ++i )
518 {
519 // move forward
520 if ( cos(entity->yaw) > .4 )
521 {
522 x++;
523 }
524 else if ( cos(entity->yaw) < -.4 )
525 {
526 x--;
527 }
528 if ( sin(entity->yaw) > .4 )
529 {
530 y++;
531 }
532 else if ( sin(entity->yaw) < -.4 )
533 {
534 y--;
535 }
536
537 // get brighter color shade
538 /*if ( foundplayer )
539 {
540 color = SDL_MapRGB(mainsurface->format, 64, 255, 64);
541 }
542 else
543 {
544 color = SDL_MapRGB(mainsurface->format, 64, 64, 255);
545 }*/
546
547 // draw the pixel
548 if ( softwaremode )
549 {
550 //SPG_Pixel(screen,(int)(players[c]->x/16)+564+x+xres/2-(status_bmp->w/2),(int)(players[c]->y/16)+yres-71+y,color); //TODO: NOT a PLAYERSWAP
551 }
552 else
553 {
554 glColor4f(((Uint8)(color >> mainsurface->format->Rshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Gshift)) / 255.f, ((Uint8)(color >> mainsurface->format->Bshift)) / 255.f, 1);
555 glBegin(GL_POINTS);
556 glVertex2f( xres - map.width * minimapTotalScale + (int)(entity->x / (16.f / minimapTotalScale)) + x, map.height * minimapTotalScale - (int)(entity->y / (16.f / minimapTotalScale)) - y );
557 glEnd();
558 }
559 }
560 }
561 }
562 }
563
564 // draw minotaur
565 if (players[clientnum] == nullptr)
566 {
567 return;
568 }
569 for ( node = map.creatures->first; node != nullptr; node = node->next )
570 {
571 Entity* entity = (Entity*)node->element;
572 if ( entity->sprite == 239 )
573 {
574 if ( ticks % 120 - ticks % 60 )
575 {
576 if ( !minotaur_timer )
577 {
578 playSound(116, 64);
579 }
580 minotaur_timer = 1;
581 if ( !colorblind )
582 {
583 color = SDL_MapRGB(mainsurface->format, 192, 0, 0);
584 }
585 else
586 {
587 color = SDL_MapRGB(mainsurface->format, 0, 192, 192);
588 }
589
590 // draw the first pixel
591 x = xres - map.width * minimapTotalScale + (int)(entity->x / (16.f / minimapTotalScale));
592 y = map.height * minimapTotalScale - (int)(entity->y / (16.f / minimapTotalScale));
593 if ( softwaremode )
594 {
595 //SPG_Pixel(screen,(int)(players[c]->x/16)+564+x+xres/2-(status_bmp->w/2),(int)(players[c]->y/16)+yres-71+y,color); //TODO: NOT a PLAYERSWAP
596 }
597 else
598 {
599 glColor4f(((Uint8)(color >> 16)) / 255.f, ((Uint8)(color >> 8)) / 255.f, ((Uint8)(color)) / 255.f, 1);
600 glBegin(GL_POINTS);
601 glVertex2f( x, y );
602 glEnd();
603 }
604
605 // draw a circle
606 drawCircle(x - 1, yres - y - 1, std::max(3 + minimapObjectZoom, 0), color, 255);
607
608 x = 0;
609 y = 0;
610 for ( i = 0; i < 4 + minimapObjectZoom; ++i )
611 {
612 // move forward
613 if ( cos(entity->yaw) > .4 )
614 {
615 x++;
616 }
617 else if ( cos(entity->yaw) < -.4 )
618 {
619 x--;
620 }
621 if ( sin(entity->yaw) > .4 )
622 {
623 y++;
624 }
625 else if ( sin(entity->yaw) < -.4 )
626 {
627 y--;
628 }
629
630 // get brighter color shade
631 if ( !colorblind )
632 {
633 color = SDL_MapRGB(mainsurface->format, 255, 64, 64);
634 }
635 else
636 {
637 color = SDL_MapRGB(mainsurface->format, 64, 255, 255);
638 }
639
640 // draw the pixel
641 if ( softwaremode )
642 {
643 //SPG_Pixel(screen,(int)(players[c]->x/16)+564+x+xres/2-(status_bmp->w/2),(int)(players[c]->y/16)+yres-71+y,color); //TODO: NOT a PLAYERSWAR
644 }
645 else
646 {
647 glColor4f(((Uint8)(color >> 16)) / 255.f, ((Uint8)(color >> 8)) / 255.f, ((Uint8)(color)) / 255.f, 1);
648 glBegin(GL_POINTS);
649 glVertex2f( xres - map.width * minimapTotalScale + (int)(entity->x / (16.f / minimapTotalScale)) + x, map.height * minimapTotalScale - (int)(entity->y / (16.f / minimapTotalScale)) - y );
650 glEnd();
651 }
652 }
653 }
654 else
655 {
656 minotaur_timer = 0;
657 }
658 }
659 }
660 }
661
minimapPingAdd(MinimapPing newPing)662 void minimapPingAdd(MinimapPing newPing)
663 {
664 int numPlayerPings = 0;
665 if ( !minimapPings.empty() )
666 {
667 for ( std::vector<MinimapPing>::iterator it = minimapPings.begin(); it != minimapPings.end();)
668 {
669 MinimapPing ping = *it;
670 if ( ping.player == newPing.player && !newPing.radiusPing )
671 {
672 ++numPlayerPings;
673 // prune pings if too many by same player.
674 if ( numPlayerPings > 3 )
675 {
676 if ( ping.player == clientnum )
677 {
678 // this is the player creating the sound source.
679 minimapPingGimpTimer = TICKS_PER_SECOND * 3; // 3 second penalty for spam.
680 }
681 it = minimapPings.erase(it);
682 continue;
683 }
684 }
685 ++it;
686 }
687 }
688 if ( !minimapPingMute && !newPing.radiusPing )
689 {
690 playSound(399, 64);
691 }
692 minimapPings.insert(minimapPings.begin(), newPing);
693 }
694