1 /*
2  *
3  *   Copyright (c) 1994, 2002, 2003  Johannes Prix
4  *   Copyright (c) 1994, 2002, 2003  Reinhard Prix
5  *
6  *
7  *  This file is part of Freedroid
8  *
9  *  Freedroid is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  Freedroid is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with Freedroid; see the file COPYING. If not, write to the
21  *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  *  MA  02111-1307  USA
23  *
24  */
25 
26 /*----------------------------------------------------------------------
27  *
28  * Desc: the konsole- and lift functions
29  *
30  *----------------------------------------------------------------------*/
31 
32 #define _ship_c
33 
34 #include "system.h"
35 
36 #include "defs.h"
37 #include "struct.h"
38 #include "global.h"
39 #include "proto.h"
40 #include "text.h"
41 #include "SDL_rotozoom.h"
42 
43 
44 int CursorIsOnRect (SDL_Rect *rect);
45 SDL_Rect up_rect,down_rect,left_rect,right_rect;
46 extern bool show_cursor;
47 
48 #define UPDATE_ONLY 0x01
49 
50 //--------------------
51 // Definitions for the menu inside the in-game console
52 //
53 #define CONS_MENU_HEIGHT 		256
54 #define CONS_MENU_LENGTH 		100
55 
56 #define WAIT_ELEVATOR		9	/* warte, bevor Lift weitergeht */
57 
58 #define MENUTEXT_X	(132 + USERFENSTERPOSX + 5 )
59 
60 
61 SDL_Rect up_rect;
62 SDL_Rect down_rect;
63 SDL_Rect left_rect;
64 SDL_Rect right_rect;
65 
66 
67 /*-----------------------------------------------------------------
68  * @Desc: does all the work when we enter a lift
69  *
70  *-----------------------------------------------------------------*/
71 void
EnterLift(void)72 EnterLift (void)
73 {
74   int i;
75   int curLevel;
76   int curLift, upLift, downLift, liftrow;
77 
78   DebugPrintf (2, "\nvoid EnterLift(void): Function call confirmed.");
79 
80   /* Prevent distortion of framerate by the delay coming from
81    * the time spend in the menu. */
82   Activate_Conservative_Frame_Computation();
83 
84 
85   /* make sure to release the fire-key */
86   SpacePressedR();
87   MouseLeftPressedR();
88   MouseRightPressedR();
89 
90   /* Prevent the influ from coming out of the lift in transfer mode
91    * by turning off transfer mode as soon as the influ enters the lift */
92   Me.status= ELEVATOR;
93 
94   ResetMouseWheel ();  // forget previous mouse-wheel action
95   SDL_ShowCursor(SDL_DISABLE);
96 
97   curLevel = CurLevel->levelnum;
98 
99   if ((curLift = GetCurrentLift ()) == -1)
100     {
101       printf ("Lift out of order, I'm so sorry !");
102       return;
103     }
104 
105   EnterLiftSound ();
106   Switch_Background_Music_To (NULL); // turn off Bg music
107 
108   upLift = curShip.AllLifts[curLift].up;
109   downLift = curShip.AllLifts[curLift].down;
110 
111   liftrow = curShip.AllLifts[curLift].lift_row;
112 
113   // clear the whole screen
114   ClearGraphMem();
115   DisplayBanner (NULL, NULL,  BANNER_FORCE_UPDATE );
116 
117   ShowLifts (curLevel, liftrow);
118 
119 
120   while (! FirePressedR())
121     {
122       if (UpPressedR () || WheelUpPressed ())
123 	if (upLift != -1)
124 	  {			/* gibt es noch einen Lift hoeher ? */
125 	    if (curShip.AllLifts[upLift].x == 99)
126 	      {
127 		DebugPrintf (0, "Lift out of order, so sorry ..");
128 	      }
129 	    else
130 	      {
131 		downLift = curLift;
132 		curLift = upLift;
133 		curLevel = curShip.AllLifts[curLift].level;
134 		upLift = curShip.AllLifts[curLift].up;
135 
136 		ShowLifts (curLevel, liftrow);
137 
138 		MoveLiftSound ();
139 	      }
140 	  }			/* if uplevel */
141 
142 
143       if (DownPressedR () || WheelDownPressed ())
144 	if (downLift != -1)
145 	  {			/* gibt es noch einen Lift tiefer ? */
146 	    if (curShip.AllLifts[downLift].x == 99)
147 	      {
148 		printf ("Lift Out of order, so sorry ..");
149 	      }
150 	    else
151 	      {
152 		upLift = curLift;
153 		curLift = downLift;
154 		curLevel = curShip.AllLifts[curLift].level;
155 		downLift = curShip.AllLifts[curLift].down;
156 
157 		ShowLifts (curLevel, liftrow);
158 
159 		MoveLiftSound ();
160 	      }
161 	  }			/* if downlevel */
162     }				/* while !SpaceReleased */
163 
164   //--------------------
165   // It might happen, that the influencer enters the elevator, but then decides to
166   // come out on the same level where he has been before.  In this case of course there
167   // is no need to reshuffle enemys or to reset influencers position.  Therefore, only
168   // when a real level change has occured, we need to do real changes as below, where
169   // we set the new level and set new position and initiate timers and all that...
170   //
171   if (curLevel != CurLevel->levelnum)
172     {				/* wirklich neu ??? */
173       int array_num = 0;
174       Level tmp;
175 
176       /* Aktuellen Level setzen */
177       while ((tmp = curShip.AllLevels[array_num]) != NULL)
178 	{
179 	  if (tmp->levelnum == curLevel)
180 	    break;
181 	  else
182 	    array_num++;
183 	}
184 
185 
186       CurLevel = curShip.AllLevels[array_num];
187 
188       // redistribute the enemys around the level
189       //      ShuffleEnemys ();
190 
191       // set the position of the influencer to the correct locatiohn
192       Me.pos.x = curShip.AllLifts[curLift].x;
193       Me.pos.y = curShip.AllLifts[curLift].y;
194 
195       for (i = 0; i < MAXBLASTS; i++)
196 	DeleteBlast( i );
197       for (i = 0; i < MAXBULLETS; i++)
198 	DeleteBullet ( i ) ;
199     } // if real level change has occured
200 
201   LeaveLiftSound ( );
202   Switch_Background_Music_To (CurLevel->Background_Song_Name);
203   ClearGraphMem ( );
204   DisplayBanner (NULL, NULL,  BANNER_FORCE_UPDATE );
205 
206   // UnfadeLevel ();
207 
208   Me.status = MOBILE;
209   Me.TextVisibleTime=0;
210   Me.TextToBeDisplayed=CurLevel->Level_Enter_Comment;
211 
212   DebugPrintf (2, "\nvoid EnterLift(void): Usual end of function reached.");
213 
214   return;
215 }	/* EnterLift */
216 
217 /*-----------------------------------------------------------------
218  * @Desc: show side-view of the ship, and hightlight the current
219  *        level + lift
220  *
221  *  if level==-1: don't highlight any level
222  *  if liftrow==-1: dont' highlight any liftrows
223  *
224  *-----------------------------------------------------------------*/
225 void
ShowLifts(int level,int liftrow)226 ShowLifts (int level, int liftrow)
227 {
228   SDL_Rect src, dst;
229   int i;
230   SDL_Color lift_bg_color = {0,0,0};  /* black... */
231   int xoffs = User_Rect.w/20;
232   int yoffs = User_Rect.h/5;
233 
234   SDL_ShowCursor (SDL_DISABLE);
235   // fill the user fenster with some color
236   Fill_Rect (User_Rect, lift_bg_color);
237 
238   /* First blit ship "lights off" */
239   Copy_Rect (User_Rect, dst);
240   SDL_SetClipRect (ne_screen, &dst);
241   Copy_Rect (User_Rect, dst);
242   dst.x += xoffs;
243   dst.y += yoffs;
244   SDL_BlitSurface (ship_off_pic, NULL, ne_screen, &dst);
245 
246   if (level >= 0)
247     for (i=0; i<curShip.num_level_rects[level]; i++)
248       {
249 	Copy_Rect (curShip.Level_Rects[level][i], src);
250 	Copy_Rect (src, dst);
251 	dst.x += User_Rect.x + xoffs;   /* offset respective to User-Rectangle */
252 	dst.y += User_Rect.y + yoffs;
253 	SDL_BlitSurface (ship_on_pic, &src, ne_screen, &dst);
254       }
255 
256   if (liftrow >=0)
257     {
258       Copy_Rect (curShip.LiftRow_Rect[liftrow], src);
259       Copy_Rect (src, dst);
260       dst.x += User_Rect.x + xoffs;   /* offset respective to User-Rectangle */
261       dst.y += User_Rect.y + yoffs;
262       SDL_BlitSurface (ship_on_pic, &src, ne_screen, &dst);
263     }
264 
265   SDL_Flip (ne_screen);
266 
267   return;
268 
269 } /* ShowLifts() */
270 
271 /*@Function============================================================
272 @Desc: EnterKonsole(): does all konsole- duties
273 This function runs the consoles. This means the following duties:
274 	2	* Show a small-scale plan of the current deck
275 	3	* Show a side-elevation on the ship
276 	1	* Give all available data on lower druid types
277 	0	* Reenter the game without squashing the colortable
278 @Ret:
279 @Int:
280 * $Function----------------------------------------------------------*/
281 void
EnterKonsole(void)282 EnterKonsole (void)
283 {
284   int ReenterGame = FALSE;
285   int i, pos, mousemove_buf;
286   SDL_Rect TmpRect;
287   // Prevent distortion of framerate by the delay coming from
288   // the time spend in the menu.
289   Activate_Conservative_Frame_Computation();
290 
291   Copy_Rect (User_Rect, TmpRect);
292   Copy_Rect (Full_User_Rect, User_Rect);
293 
294   // make sure to release fire keys
295   SpacePressedR();
296   MouseLeftPressedR();
297   MouseRightPressedR();
298 
299   ResetMouseWheel ();
300 
301   Me.status = CONSOLE;
302 
303   SDL_SetCursor (arrow_cursor);
304 
305   SetCurrentFont( Para_BFont );
306 
307   pos = 0;   // starting menu position
308   PaintConsoleMenu (pos, 0);
309 
310   /* Gesamtkonsolenschleife */
311 
312   while (!ReenterGame)
313     {
314       SDL_Delay(1);
315       if (show_cursor) SDL_ShowCursor (SDL_ENABLE);
316       else SDL_ShowCursor (SDL_DISABLE);
317 
318       if (EscapePressedR() || MouseRightPressedR())
319 	ReenterGame = TRUE;
320 
321       if (UpPressedR () || WheelUpPressed())
322 	{
323 	  MoveMenuPositionSound ();
324 	  if (pos > 0) pos--;
325 	  else pos = 3;
326 	  // when warping the mouse-cursor: don't count that as a mouse-activity
327 	  // this is a dirty hack, but that should be enough for here...
328 	  mousemove_buf = last_mouse_event;
329 	  if (show_cursor)
330 	    SDL_WarpMouse (Cons_Menu_Rects[pos].x+Cons_Menu_Rects[pos].w/2,
331 			   Cons_Menu_Rects[pos].y+Cons_Menu_Rects[pos].h/2);
332 	  keyboard_update ();  // this sets a new last_mouse_event
333 	  last_mouse_event = mousemove_buf; //... which we override.. ;)
334 
335 
336 	  PaintConsoleMenu (pos, UPDATE_ONLY);
337 	}
338       if (DownPressedR () || WheelDownPressed())
339 	{
340 	  MoveMenuPositionSound ();
341 	  if (pos < 3) pos++;
342 	  else pos = 0;
343 	  // when warping the mouse-cursor: don't count that as a mouse-activity
344 	  // this is a dirty hack, but that should be enough for here...
345 	  mousemove_buf = last_mouse_event;
346 	  if (show_cursor)
347 	    SDL_WarpMouse (Cons_Menu_Rects[pos].x+Cons_Menu_Rects[pos].w/2,
348 			   Cons_Menu_Rects[pos].y+Cons_Menu_Rects[pos].h/2);
349 	  keyboard_update ();  // this sets a new last_mouse_event
350 	  last_mouse_event = mousemove_buf; //... which we override.. ;)
351 
352 	  PaintConsoleMenu (pos, UPDATE_ONLY);
353 	}
354 
355       // check if the mouse-cursor is on any of the console-menu points
356       for (i=0; i < 4; i++)
357 	if (show_cursor && (pos != i) && CursorIsOnRect(&Cons_Menu_Rects[i]) )
358 	  {
359 	    MoveMenuPositionSound ();
360 	    pos = i;
361 	    PaintConsoleMenu (pos, UPDATE_ONLY);
362 	  }
363 
364       if (FirePressedR())
365 	{
366 	  MenuItemSelectedSound();
367 	  switch (pos)
368 	    {
369 	    case 0:
370 	      ReenterGame = TRUE;
371 	      break;
372 	    case 1:
373 	      GreatDruidShow ();
374 	      PaintConsoleMenu (pos, 0);
375 	      break;
376 	    case 2:
377 	      ClearGraphMem();
378 	      DisplayBanner (NULL, NULL, BANNER_FORCE_UPDATE);
379 	      ShowDeckMap (CurLevel);
380 	      PaintConsoleMenu(pos, 0);
381 	      break;
382 	    case 3:
383 	      ClearGraphMem();
384 	      DisplayBanner (NULL, NULL, BANNER_FORCE_UPDATE);
385 	      ShowLifts (CurLevel->levelnum, -1);
386 
387 	      while (! (FirePressedR() || EscapePressedR() || MouseRightPressedR() ))
388 		SDL_Delay(1);
389 	      PaintConsoleMenu(pos, 0);
390 	      break;
391 	    default:
392 	      DebugPrintf (1, "Konsole menu out of bounds... pos = %d", pos);
393 	      pos = 0;
394 	      break;
395 	    } // switch
396 	} // if SpacePressed
397 
398     }	/* (while !ReenterGane) */
399 
400   Copy_Rect (TmpRect, User_Rect);
401 
402   Me.status = MOBILE;
403 
404   ClearGraphMem();
405 
406   SDL_SetCursor (crosshair_cursor);
407   if (!show_cursor)
408     SDL_ShowCursor (SDL_DISABLE);
409 
410   return;
411 
412 } // void EnterKonsole(void)
413 
414 /*-----------------------------------------------------------------
415  * @Desc: diese Funktion zeigt die m"oglichen Auswahlpunkte des Menus
416  *    Sie soll die Schriftfarben nicht ver"andern
417  *
418  *  NOTE: this function does not actually _display_ anything yet,
419  *        it just prepares the display, so you need
420  *        to call SDL_Flip() to display the result!
421  *  pos  : 0<=pos<=3: which menu-position is currently active?
422  *  flag : UPDATE_ONLY  only update the console-menu bar, not text & background
423  *-----------------------------------------------------------------*/
424 void
PaintConsoleMenu(int pos,int flag)425 PaintConsoleMenu (int pos, int flag)
426 {
427   char MenuText[200];
428   SDL_Rect src;
429 
430   if ( !(flag & UPDATE_ONLY) )
431     {
432       ClearGraphMem ();
433       SDL_SetClipRect ( ne_screen , NULL );
434       SDL_BlitSurface( console_bg_pic1 , NULL , ne_screen , NULL );
435 
436       DisplayBanner (NULL, NULL,  BANNER_FORCE_UPDATE );
437 
438       sprintf (MenuText, "Area : %s\nDeck : %s    Alert: %s",
439 	       curShip.AreaName, CurLevel->Levelname, Alertcolor[AlertLevel]);
440       DisplayText (MenuText, Cons_Header_Rect.x, Cons_Header_Rect.y, &Cons_Header_Rect);
441 
442       sprintf (MenuText, "Logout from console\n\nDroid info\n\nDeck map\n\nShip map");
443       DisplayText (MenuText, Cons_Text_Rect.x, Cons_Text_Rect.y+25, &Cons_Text_Rect);
444 
445     } // only if not UPDATE_ONLY was required
446 
447   src.x = Cons_Menu_Rects[0].w * pos;
448   src.y = 0;
449   src.w = Cons_Menu_Rect.w;
450   src.h = 4 * Cons_Menu_Rect.h;
451   SDL_BlitSurface (console_pic, &src, ne_screen, &Cons_Menu_Rect);
452 
453   SDL_Flip (ne_screen);
454 
455   return;
456 }	// PaintConsoleMenu ()
457 
458 /*-----------------------------------------------------------------
459  * @Desc: Displays the concept view of Level "deck" in Userfenster
460  *
461  *	Note: we no longer wait here for a key-press, but return
462  *            immediately
463  *-----------------------------------------------------------------*/
464 void
ShowDeckMap(Level deck)465 ShowDeckMap (Level deck)
466 {
467   finepoint tmp;
468   tmp.x=Me.pos.x;
469   tmp.y=Me.pos.y;
470 
471   Me.pos.x = CurLevel->xlen/2;
472   Me.pos.y = CurLevel->ylen/2;
473 
474   SDL_ShowCursor (SDL_DISABLE);
475 
476   SetCombatScaleTo( 0.25 );
477 
478   Assemble_Combat_Picture( ONLY_SHOW_MAP|SHOW_FULL_MAP );
479 
480   SDL_Flip (ne_screen);
481 
482   Me.pos.x=tmp.x;
483   Me.pos.y=tmp.y;
484 
485   while (! (FirePressedR() || EscapePressedR() || MouseRightPressedR() ))
486     SDL_Delay(1);
487 
488   SetCombatScaleTo (1.0);
489 
490   return;
491 } /* ShowDeckMap() */
492 
493 /*@Function============================================================
494 @Desc:
495 
496 @Ret:
497 @Int:
498 * $Function----------------------------------------------------------*/
499 int
LevelEmpty(void)500 LevelEmpty (void)
501 {
502   int i;
503   int levelnum = CurLevel->levelnum;
504 
505   if (CurLevel->empty)
506     return TRUE;
507 
508   for (i = 0; i < NumEnemys; i++)
509     {
510       if ((AllEnemys[i].levelnum == levelnum) &&
511 	  ( (AllEnemys[i].status != OUT) && (AllEnemys[i].status != TERMINATED) ) )
512 	return FALSE;
513     }
514 
515   return TRUE;
516 }
517 
518 /* ----------------------------------------------------------------------
519  * This function should check if the mouse cursor is in the given Rectangle
520  * ---------------------------------------------------------------------- */
521 int
CursorIsOnRect(SDL_Rect * rect)522 CursorIsOnRect (SDL_Rect *rect)
523 {
524   point CurPos;
525 
526   CurPos.x = input_axis.x + (UserCenter_x - 16);
527   CurPos.y = input_axis.y + (UserCenter_y - 16);
528 
529   if ( (CurPos.x >= rect->x) && (CurPos.x <= rect->x + rect->w) )
530     if ( (CurPos.y >= rect->y) && (CurPos.y <= rect->y + rect->h) )
531       return (TRUE);
532 
533   return (FALSE);
534 
535 }; // int CursorIsOnRect
536 
537 /* ----------------------------------------------------------------------
538  * This function does the robot show when the user has selected robot
539  * show from the console menu.
540  * ---------------------------------------------------------------------- */
541 void
GreatDruidShow(void)542 GreatDruidShow (void)
543 {
544   int droidtype;
545   int page;
546   bool finished = FALSE;
547   bool key = FALSE;
548 
549   droidtype = Me.type;
550   page = 0;
551 
552   show_droid_info (droidtype, page, 0);
553   show_droid_portrait (Cons_Droid_Rect, droidtype, 0.0, UPDATE|RESET);
554 
555   SpacePressedR();
556   MouseLeftPressedR();
557 
558   while (!finished)
559     {
560       show_droid_portrait (Cons_Droid_Rect, droidtype, DROID_ROTATION_TIME, 0);
561       SDL_Delay(1);
562       if (show_cursor) SDL_ShowCursor (SDL_ENABLE);
563       else SDL_ShowCursor (SDL_DISABLE);
564 
565       if (key)
566 	{
567 	  show_droid_info (droidtype, page, UPDATE_ONLY);
568 	  show_droid_portrait (Cons_Droid_Rect, droidtype, DROID_ROTATION_TIME, UPDATE);
569 	  key = FALSE;
570 	}
571 
572       if (MouseLeftPressedR ())
573 	{
574 	  if ( CursorIsOnRect (&left_rect) && (page > 0) )
575 	    {
576 	      page --;
577 	      MoveMenuPositionSound();
578 	      key = TRUE;
579 	    }
580 	  else if (CursorIsOnRect (&right_rect) && (page < 2) )
581 	    {
582 	      page ++;
583 	      MoveMenuPositionSound();
584 	      key = TRUE;
585 	    }
586 	  else if (CursorIsOnRect (&up_rect) && (droidtype < Me.type) )
587 	    {
588 	      droidtype ++;
589 	      MoveMenuPositionSound();
590 	      key = TRUE;
591 	    }
592 	  else if (CursorIsOnRect (&down_rect) && (droidtype > 0))
593 	    {
594 	      droidtype --;
595 	      MoveMenuPositionSound();
596 	      key = TRUE;
597 	    }
598 	}
599       if (SpacePressedR() || EscapePressedR() || MouseRightPressedR())
600 	finished = TRUE;
601 
602       if ( (UpPressedR()||WheelUpPressed()) && (droidtype < Me.type) )
603 	{
604 	  droidtype ++;
605 	  MoveMenuPositionSound();
606 	  key = TRUE;
607 	}
608       if ( (DownPressedR()||WheelDownPressed()) && (droidtype > 0) )
609 	{
610 	  droidtype --;
611 	  MoveMenuPositionSound();
612 	  key = TRUE;
613 	}
614       if (RightPressedR() && (page < 2) )
615 	{
616 	  page ++;
617 	  MoveMenuPositionSound();
618 	  key = TRUE;
619 	}
620       if (LeftPressedR() && (page > 0) )
621 	{
622 	  page --;
623 	  MoveMenuPositionSound();
624 	  key = TRUE;
625 	}
626 
627     } /* while !finished */
628 
629   return;
630 }; // void GreatDroidShow( void )
631 
632 /*------------------------------------------------------------
633  * display infopage page of droidtype
634  *
635  * if flags == UPDATE_ONLY : don't blit a new background&banner,
636  *                           only  update the text-regions
637  *
638  *  does update the screen: all if flags=0, text-rect if flags=UPDATE_ONLY
639  *
640  *------------------------------------------------------------*/
641 void
show_droid_info(int droidtype,int page,int flags)642 show_droid_info (int droidtype, int page, int flags)
643 {
644   char InfoText[1000];
645   char DroidName[80];
646   bool show_title = FALSE;
647   bool show_arrows = FALSE;
648   int lineskip, lastline;
649 
650   SDL_SetClipRect ( ne_screen , NULL );
651   SetCurrentFont( Para_BFont );
652 
653   lineskip = FontHeight (GetCurrentFont()) * TEXT_STRETCH;
654   lastline = Cons_Header_Rect.y + Cons_Header_Rect.h;
655   Set_Rect(up_rect,   Cons_Header_Rect.x, lastline - 1.0*lineskip, 25, 13);
656   Set_Rect(down_rect, Cons_Header_Rect.x, lastline - 0.5*lineskip, 25, 13);
657   Set_Rect(left_rect, Cons_Header_Rect.x + Cons_Header_Rect.w - 1.5*lineskip, lastline - 0.9*lineskip,13,25);
658   Set_Rect(right_rect,Cons_Header_Rect.x + Cons_Header_Rect.w - 1.0*lineskip, lastline - 0.9*lineskip,13,25);
659 
660   //  Fill_Rect (Cons_Header_Rect, Black);  // for debugging menu-rects...
661 
662   sprintf (DroidName, "  Unit type %s - %s", Druidmap[droidtype].druidname,
663 	   Classname[Druidmap[droidtype].class]);
664 
665   switch (page)
666     {
667     case -3: // Title screen: intro unit
668       sprintf (InfoText, "This is the unit that you currently control. Prepare to board Robo-frighter \
669 Paradroid to eliminate all rogue robots.");
670       break;
671     case -2: // Takeover: unit that you wish to control
672       sprintf (InfoText, "This is the unit that you wish to control.\n\n Prepare to takeover.");
673       break;
674     case -1: // Takeover: unit that you control
675       sprintf (InfoText, "This is the unit that you currently control.");
676       break;
677     case 0:
678       show_title = TRUE;
679       show_arrows = TRUE;
680       sprintf (InfoText, "\
681 Entry : %02d\n\
682 Class : %s\n\
683 Height : %5.2f m\n\
684 Weight: %d kg\n\
685 Drive : %s \n\
686 Brain : %s",   droidtype+1, Classes[Druidmap[droidtype].class],
687 	       Druidmap[droidtype].height, Druidmap[droidtype].weight,
688 	       Drivenames [ Druidmap[ droidtype].drive],
689 	       Brainnames[ Druidmap[droidtype].brain ]);
690       break;
691     case 1:
692       show_title = TRUE;
693       show_arrows = TRUE;
694       sprintf( InfoText , "\
695 Armament : %s\n\
696 Sensors  1: %s\n\
697                     2: %s\n\
698                     3: %s",
699 	       Weaponnames [ Druidmap[droidtype].gun],
700 	       Sensornames[ Druidmap[droidtype].sensor1 ],
701 	       Sensornames[ Druidmap[droidtype].sensor2 ],
702 	       Sensornames[ Druidmap[droidtype].sensor3 ]);
703       break;
704     case 2:
705       show_title = TRUE;
706       show_arrows = TRUE;
707       sprintf (InfoText, "Notes: %s", Druidmap[droidtype].notes);
708       break;
709     default:
710       sprintf (InfoText, "ERROR: Page not implemented!! \nPlease report bug!");
711       break;
712     } /* switch (page) */
713 
714 
715 
716   // if UPDATE_ONLY then the background has not been cleared, so we have do it
717   // it for each menu-rect:
718   if (flags & UPDATE_ONLY)
719     {
720       SDL_SetClipRect (ne_screen, &Cons_Text_Rect);
721       SDL_BlitSurface (console_bg_pic2, NULL, ne_screen, NULL);
722       SDL_SetClipRect (ne_screen, &Cons_Header_Rect);
723       SDL_BlitSurface (console_bg_pic2, NULL, ne_screen, NULL);
724       SDL_SetClipRect (ne_screen, NULL);
725     }
726   else // otherwise we just redraw the whole screen
727     {
728       SDL_BlitSurface (console_bg_pic2, NULL, ne_screen, NULL);
729       DisplayBanner (NULL, NULL,  BANNER_NO_SDL_UPDATE | BANNER_FORCE_UPDATE );
730     }
731 
732   DisplayText (InfoText, Cons_Text_Rect.x, Cons_Text_Rect.y, &Cons_Text_Rect);
733 
734   DisplayText (DroidName, Cons_Header_Rect.x + lineskip , lastline - 0.9*lineskip, NULL);
735 
736   if (show_arrows)
737     {
738       if (Me.type >  droidtype)
739 	SDL_BlitSurface ( arrow_up, NULL, ne_screen, &up_rect);
740 
741       if (droidtype > 0)
742 	SDL_BlitSurface ( arrow_down, NULL, ne_screen, &down_rect);
743 
744       if (page > 0)
745 	SDL_BlitSurface ( arrow_left, NULL, ne_screen, &left_rect);
746 
747       if (page < 2)
748 	SDL_BlitSurface ( arrow_right, NULL, ne_screen, &right_rect);
749     }
750 
751   if (flags & UPDATE_ONLY)
752     {
753       SDL_UpdateRects (ne_screen, 1, &Cons_Header_Rect);
754       SDL_UpdateRects (ne_screen, 1, &Cons_Text_Rect);
755     }
756   else
757     SDL_Flip (ne_screen);
758 
759   return;
760 
761 } /* show_droid_info */
762 
763 
764 //----------------------------------------------------------------------
765 // show a an animated droid-pic: automatically counts frames and frametimes
766 // stored internally, so you just have to keep calling this function to get
767 // an animation. The target-rect dst is only updated when a new frame is set
768 // if flags & RESET: to restart a fresh animation at frame 0
769 // if flags & UPDATE: force a blit of droid-pic
770 //
771 // cycle_time is the time in seconds for a full animation-cycle,
772 // if cycle_time == 0 : display static pic, using only first frame
773 //
774 //----------------------------------------------------------------------
775 void
show_droid_portrait(SDL_Rect dst,int droid_type,float cycle_time,int flags)776 show_droid_portrait (SDL_Rect dst, int droid_type, float cycle_time, int flags)
777 {
778   static SDL_Surface *background = NULL;
779   static SDL_Surface *droid_pics = NULL;
780   static int frame_num = 0;
781   static int last_droid_type = -1;
782   static Uint32 last_frame_time = 0;
783   static SDL_Rect src_rect;
784   SDL_Surface *tmp;
785   Uint32 frame_duration;
786   bool need_new_frame = FALSE;
787   int num_frames;
788 
789   SDL_SetClipRect (ne_screen, &dst);
790 
791   if (!background) // first call
792     {
793       tmp = SDL_CreateRGBSurface (0, dst.w, dst.h, screen_bpp, 0, 0, 0, 0);
794       background = SDL_DisplayFormat (tmp);
795       SDL_FreeSurface (tmp);
796       SDL_BlitSurface (ne_screen, &dst, background, NULL);
797       Copy_Rect (Portrait_Rect, src_rect);
798     }
799 
800   if (flags & RESET)
801     {
802       SDL_BlitSurface (ne_screen, &dst, background, NULL);
803       frame_num  = 0;
804       last_frame_time = SDL_GetTicks ();
805     }
806 
807   if ( (droid_type != last_droid_type) || (droid_pics == NULL))
808     { // we need to unpack the droid-pics into our local storage
809       if (droid_pics) SDL_FreeSurface (droid_pics);
810       droid_pics = NULL;
811       tmp = IMG_Load_RW (packed_portraits[droid_type], 0);
812       // important: return seek-position to beginning of RWops for next operation to succeed!
813       SDL_RWseek (packed_portraits[droid_type], 0, SEEK_SET);
814       if (!tmp)
815 	{
816 	  DebugPrintf (0, "ERROR: failed to unpack droid-portraits of droid-type %d\n", droid_type);
817 	  return; // ok, so no pic but we continue ;)
818 	}
819       // now see if its a jpg, then we add some transparency by color-keying:
820       if (IMG_isJPG(packed_portraits[droid_type]))
821 	{
822 	  droid_pics = SDL_DisplayFormat (tmp);
823 	} // else assume it's png ;)
824       else
825 	{
826 	  droid_pics = SDL_DisplayFormatAlpha (tmp);
827 	}
828       SDL_FreeSurface (tmp);
829       SDL_RWseek (packed_portraits[droid_type], 0, SEEK_SET);
830 
831 
832       // do we have to scale the droid pics
833       if (GameConfig.scale != 1.0)
834 	ScalePic (&droid_pics, GameConfig.scale);
835 
836       last_droid_type = droid_type;
837     }
838 
839   num_frames = droid_pics->w / Portrait_Rect.w;
840 
841   // sanity check
842   if ( num_frames == 0)
843     {
844       DebugPrintf (0, "WARNING: Only one frame found. Width droid-pics=%d, Frame-width=%d\n",
845 		   droid_pics->w, Portrait_Rect.w);
846       num_frames = 1;       // continue and hope for the best
847     }
848 
849   frame_duration = SDL_GetTicks() - last_frame_time;
850 
851   if (cycle_time && (frame_duration >  1000.0*cycle_time/num_frames) )
852     {
853       need_new_frame = TRUE;
854       frame_num ++;
855     }
856 
857   if (frame_num >= num_frames)
858     frame_num = 0;
859 
860   if ( (flags & (RESET|UPDATE)) || need_new_frame)
861     {
862       src_rect.x = frame_num*src_rect.w;
863 
864       SDL_BlitSurface (background, NULL, ne_screen, &dst);
865       SDL_BlitSurface (droid_pics, &src_rect, ne_screen, &dst);
866 
867       SDL_UpdateRects (ne_screen, 1, &dst);
868 
869       last_frame_time = SDL_GetTicks();
870 
871     }
872 
873   SDL_SetClipRect (ne_screen, NULL);
874 
875   return;
876 
877 } // show_droid_portrait
878 
879 // ----------------------------------------------------------------------
880 // do all alert-related agitations: alert-sirens and alert-lights
881 // ----------------------------------------------------------------------
882 #define SIREN_WAIT 2.5
883 #define BLINK_WAIT 0.2
884 void
AlertLevelWarning(void)885 AlertLevelWarning (void)
886 {
887   static Uint32 last_siren = 0;
888   //  static Uint32 last_blink = 0;
889   int i, posx, posy;
890   int cur_alert = 0;
891 
892 
893   switch (AlertLevel)
894     {
895     case AL_GREEN:
896       break;
897     case AL_YELLOW:
898     case AL_AMBER:
899     case AL_RED:
900       if (SDL_GetTicks() - last_siren > SIREN_WAIT * 1000.0 / AlertLevel)  // higher alert-> faster sirens!
901 	{
902 	  Play_Sound (ALERT_SOUND);
903 	  last_siren = SDL_GetTicks ();
904 	}
905       break;
906     default:
907       DebugPrintf (0, "WARNING: illegal AlertLevel = %d > %d.. something's gone wrong!!\n",
908 		   AlertLevel, AL_RED);
909       break;
910     }
911 
912   // so much to the sirens, now make sure the alert-tiles are updated correctly:
913   posx = CurLevel->alerts[0].x;
914   posy = CurLevel->alerts[0].y;
915   if (posx == -1) return;  // no alerts here...
916 
917 
918   cur_alert = ALERT_GREEN + AlertLevel;
919 
920   // check if alert-tiles are up-to-date
921   if (GetMapBrick(CurLevel, posx, posy) == cur_alert)
922     return; // ok
923 
924   for (i=0; i< MAX_ALERTS_ON_LEVEL; i++)
925     {
926       posx = CurLevel->alerts[i].x;
927       posy = CurLevel->alerts[i].y;
928       if ( posx == -1) 	break;
929 
930       CurLevel->map[posy][posx] = cur_alert;
931     }
932 
933   return;
934 }
935 
936 #undef _ship_c
937