2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Hud/HUDets.cpp $
15 * C file that contains code to manage and display the Energy Transfer System (ETS)
18 * Revision 1.4 2005/08/12 08:52:32 taylor
19 * various GCC4 warning fixes
21 * Revision 1.3 2002/06/09 04:41:21 relnev
22 * added copyright header
24 * Revision 1.2 2002/05/07 03:16:45 theoddone33
25 * The Great Newline Fix
27 * Revision 1.1.1.1 2002/05/03 03:28:09 root
31 * 14 10/28/99 11:17p Jefff
32 * nudged German "A" on ETS
34 * 13 10/26/99 11:02p Jefff
35 * changed german ets labels
37 * 12 9/05/99 11:23p Jimb
38 * changed weapon and shield recharge rates for skill levels
40 * 11 9/03/99 2:28p Mikek
41 * Slightly increase rate of weapon recharge at Medium and Hard. Slightly
44 * 10 8/01/99 12:39p Dave
45 * Added HUD contrast control key (for nebula).
47 * 9 6/10/99 3:43p Dave
48 * Do a better job of syncing text colors to HUD gauges.
50 * 8 2/23/99 8:11p Dave
51 * Tidied up dogfight mode. Fixed TvT ship type problems for alpha wing.
52 * Small pass over todolist items.
54 * 7 1/07/99 9:06a Jasen
57 * 6 12/28/98 3:17p Dave
58 * Support for multiple hud bitmap filenames for hi-res mode.
60 * 5 12/21/98 5:02p Dave
61 * Modified all hud elements to be multi-resolution friendly.
63 * 4 11/05/98 4:18p Dave
64 * First run nebula support. Beefed up localization a bit. Removed all
65 * conditional compiles for foreign versions. Modified mission file
68 * 3 10/13/98 9:28a Dave
69 * Started neatening up freespace.h. Many variables renamed and
70 * reorganized. Added AlphaColors.[h,cpp]
72 * 2 10/07/98 10:53a Dave
75 * 1 10/07/98 10:49a Dave
77 * 60 8/28/98 3:28p Dave
78 * EMP effect done. AI effects may need some tweaking as required.
80 * 59 8/25/98 1:48p Dave
81 * First rev of EMP effect. Player side stuff basically done. Next comes
84 * 58 6/19/98 3:49p Lawrance
87 * 57 4/07/98 1:53p Lawrance
88 * Make energy system matter more.
90 * 56 3/26/98 5:26p John
91 * added new paging code. nonfunctional.
93 * 55 2/23/98 6:49p Lawrance
94 * Use gr_aabitmap_ex() instead of clipping regions
96 * 54 2/22/98 4:17p John
97 * More string externalization classification... 190 left to go!
99 * 53 2/12/98 4:58p Lawrance
100 * Change to new flashing method.
102 * 52 1/19/98 11:37p Lawrance
103 * Fixing Optimization build warnings
105 * 51 1/05/98 9:38p Lawrance
106 * Implement flashing HUD gauges.
108 * 50 1/02/98 9:10p Lawrance
109 * Big changes to how colors get set on the HUD.
111 * 49 12/30/97 4:28p Lawrance
112 * remove .ani extensions from filenames
114 * 48 12/01/97 12:27a Lawrance
115 * redo default alpha color for HUD, make it easy to modify in the future
117 * 47 11/15/97 6:10p Lawrance
118 * make ship speed less dependant on engine damage
120 * 46 11/11/97 12:58a Lawrance
121 * deal with situation where ship has no shields
123 * 45 11/10/97 2:58p Lawrance
124 * fix bug that was preventing engine damage from affecting AI ships
126 * 44 11/09/97 3:25p Lawrance
127 * increase default alpha color
129 * 43 11/06/97 10:32a Lawrance
130 * brighten up energy management bars
132 * 42 11/05/97 11:19p Lawrance
133 * implement new ETS gauge
135 * 41 11/05/97 4:04p Lawrance
136 * engine speed not affected on Trainee ONLY for player ship
138 * 40 10/28/97 3:35p Lawrance
139 * subsystems will not be affected when playing on lowest skill level
148 #include "freespace.h"
156 #include "localize.h"
158 #define ENERGY_DIVERT_DELTA 0.2f // percentage of energy transferred in a shield->weapon or weapon->shield energy transfer
159 #define INTIAL_SHIELD_RECHARGE_INDEX 4 // default shield charge rate (index in Energy_levels[])
160 #define INTIAL_WEAPON_RECHARGE_INDEX 4 // default weapon charge rate (index in Energy_levels[])
161 #define INTIAL_ENGINE_RECHARGE_INDEX 4 // default engine charge rate (index in Energy_levels[])
163 #define MAX_SHIELD_REGEN_PER_SECOND 0.02f // max percent/100 of shield energy regenerated per second
164 #define MAX_WEAPON_REGEN_PER_SECOND 0.04f // max percent/100 of weapon energy regenerated per second
166 #define NUM_ENERGY_LEVELS 13
167 #define MAX_ENERGY_INDEX (NUM_ENERGY_LEVELS - 1)
168 float Energy_levels[NUM_ENERGY_LEVELS] = {0.0f, 0.0833f, 0.167f, 0.25f, 0.333f, 0.417f, 0.5f, 0.583f, 0.667f, 0.75f, 0.833f, 0.9167f, 1.0f};
170 #define AI_MODIFY_ETS_INTERVAL 500 // time between ets modifications for ai's (in milliseconds)
172 int Weapon_energy_cheat = 0;
174 // skill level scaling of the amount of energy that is allocated to the weapons and
176 float Skill_level_weapon_energy_scale[NUM_SKILL_LEVELS] = {10.0f, 4.0f, 2.5f, 2.0f, 1.5f};
177 float Skill_level_shield_energy_scale[NUM_SKILL_LEVELS] = {4.0f, 2.0f, 1.5f, 1.25f, 1.0f};
180 #define ONE_THIRD_INDEX 4
181 #define ONE_HALF_INDEX 6
184 #define HAS_ENGINES (1<<0)
185 #define HAS_SHIELDS (1<<1)
186 #define HAS_WEAPONS (1<<2)
188 int ETS_bar_h[GR_NUM_RESOLUTIONS] = {
193 typedef struct ets_gauge_info
196 int letter_coords[2];
198 int bottom_coords[2];
201 ets_gauge_info Ets_gauge_info_german[GR_NUM_RESOLUTIONS][3] =
204 { 'G', {525,422}, {523,380}, {523,430} },
205 { 'S', {542,422}, {540,380}, {540,430} },
206 { 'A', {559,422}, {557,380}, {557,430} }
209 { 'G', {882,690}, {880,648}, {880,698} },
210 { 'S', {900,690}, {898,648}, {898,698} },
211 { 'A', {917,690}, {916,648}, {916,698} }
214 ets_gauge_info Ets_gauge_info_french[GR_NUM_RESOLUTIONS][3] =
217 { 'C', {525,422}, {523,380}, {523,430} },
218 { 'B', {542,422}, {540,380}, {540,430} },
219 { 'M', {560,422}, {557,380}, {557,430} }
222 { 'C', {882,690}, {880,648}, {880,698} },
223 { 'B', {900,690}, {898,648}, {898,698} },
224 { 'M', {918,690}, {916,648}, {916,698} }
227 ets_gauge_info Ets_gauge_info_english[GR_NUM_RESOLUTIONS][3] =
230 { 'G', {525,422}, {523,380}, {523,430} },
231 { 'S', {542,422}, {540,380}, {540,430} },
232 { 'E', {560,422}, {557,380}, {557,430} }
235 { 'G', {882,690}, {880,648}, {880,698} },
236 { 'S', {900,690}, {898,648}, {898,698} },
237 { 'E', {918,690}, {916,648}, {916,698} }
240 ets_gauge_info *Ets_gauge_info = NULL;
242 char Ets_fname[GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN] = {
247 hud_frames Ets_gauge;
249 static int Hud_ets_inited = 0;
253 if ( Hud_ets_inited )
256 Ets_gauge.first_frame = bm_load_animation(Ets_fname[gr_screen.res], &Ets_gauge.num_frames);
257 if ( Ets_gauge.first_frame < 0 ) {
258 Warning(LOCATION,"Cannot load hud ani: Ets_fname[gr_screen.res]\n");
262 Ets_gauge_info = Ets_gauge_info_german[gr_screen.res];
264 Ets_gauge_info = Ets_gauge_info_french[gr_screen.res];
266 Ets_gauge_info = Ets_gauge_info_english[gr_screen.res];
272 // -------------------------------------------------------------------------------------------------
273 // ets_init_ship() is called by a ship when it is created (effectively, for every ship at the start
274 // of a mission). This will set the default charge rates for the different systems and initalialize
275 // the weapon energy reserve.
277 void ets_init_ship(object* obj)
281 // fred should bail here
286 Assert(obj->type == OBJ_SHIP);
287 sp = &Ships[obj->instance];
289 sp->weapon_energy = Ship_info[sp->ship_info_index].max_weapon_reserve;
290 sp->next_manage_ets = timestamp(AI_MODIFY_ETS_INTERVAL);
291 set_default_recharge_rates(obj);
294 // -------------------------------------------------------------------------------------------------
295 // update_ets() is called once per frame for every OBJ_SHIP in the game. The amount of energy
296 // to send to the weapons and shields is calculated, and the top ship speed is calculated. The
297 // amount of time elapsed from the previous call is passed in as the parameter fl_frametime.
299 // parameters: obj ==> object that is updating their energy system
300 // fl_frametime ==> game frametime (in seconds)
302 void update_ets(object* objp, float fl_frametime)
304 float max_new_shield_energy, max_new_weapon_energy, _ss;
306 if ( fl_frametime <= 0 ){
310 ship* ship_p = &Ships[objp->instance];
311 ship_info* sinfo_p = &Ship_info[ship_p->ship_info_index];
313 if ( ship_p->flags & SF_DYING ){
317 if ( sinfo_p->power_output == 0 ){
321 // new_energy = fl_frametime * sinfo_p->power_output;
323 // update weapon energy
324 max_new_weapon_energy = fl_frametime * MAX_WEAPON_REGEN_PER_SECOND * sinfo_p->max_weapon_reserve;
325 if ( objp->flags & OF_PLAYER_SHIP ) {
326 ship_p->weapon_energy += Energy_levels[ship_p->weapon_recharge_index] * max_new_weapon_energy * Skill_level_weapon_energy_scale[Game_skill_level];
328 ship_p->weapon_energy += Energy_levels[ship_p->weapon_recharge_index] * max_new_weapon_energy;
331 if ( ship_p->weapon_energy > sinfo_p->max_weapon_reserve ){
332 ship_p->weapon_energy = sinfo_p->max_weapon_reserve;
336 max_new_shield_energy = fl_frametime * MAX_SHIELD_REGEN_PER_SECOND * sinfo_p->shields;
337 if ( objp->flags & OF_PLAYER_SHIP ) {
338 shield_delta = Energy_levels[ship_p->shield_recharge_index] * max_new_shield_energy * Skill_level_shield_energy_scale[Game_skill_level];
340 shield_delta = Energy_levels[ship_p->shield_recharge_index] * max_new_shield_energy;
343 add_shield_strength(objp, shield_delta);
345 if ( (_ss = get_shield_strength(objp)) > sinfo_p->shields ){
346 for (int i=0; i<MAX_SHIELD_SECTIONS; i++){
347 objp->shields[i] *= sinfo_p->shields/ _ss;
351 // calculate the top speed of the ship based on the energy flow to engines
352 float y = Energy_levels[ship_p->engine_recharge_index];
354 // check for a shortcuts first before doing linear interpolation
355 if ( y == Energy_levels[INTIAL_ENGINE_RECHARGE_INDEX] ){
356 ship_p->current_max_speed = sinfo_p->max_speed;
357 } else if ( y == 0.0f ){
358 ship_p->current_max_speed = 0.5f * sinfo_p->max_speed;
359 } else if ( y == 1.0f ){
360 ship_p->current_max_speed = sinfo_p->max_overclocked_speed;
362 // do a linear interpolation to find the current max speed, using points (0,1/2 default_max_speed) (.333,default_max_speed)
363 // x = x1 + (y-y1) * (x2-x1) / (y2-y1);
364 if ( y < Energy_levels[INTIAL_ENGINE_RECHARGE_INDEX] ){
365 ship_p->current_max_speed = 0.5f*sinfo_p->max_speed + (y * (0.5f*sinfo_p->max_speed) ) / Energy_levels[INTIAL_ENGINE_RECHARGE_INDEX];
367 // do a linear interpolation to find the current max speed, using points (.333,default_max_speed) (1,max_overclock_speed)
368 ship_p->current_max_speed = sinfo_p->max_speed + (y - Energy_levels[INTIAL_ENGINE_RECHARGE_INDEX]) * (sinfo_p->max_overclocked_speed - sinfo_p->max_speed) / (1.0f - Energy_levels[INTIAL_ENGINE_RECHARGE_INDEX]);
372 // AL 11-15-97: Rules for engine strength affecting max speed:
373 // 1. if strength >= 0.5 no affect
374 // 2. if strength < 0.5 then max_speed = sqrt(strength)
376 // This will translate to 71% max speed at 50% engines, and 31% max speed at 10% engines
378 float strength = ship_get_subsystem_strength(ship_p, SUBSYSTEM_ENGINE);
380 // don't let engine strength affect max speed when playing on lowest skill level
381 if ( (objp != Player_obj) || (Game_skill_level > 0) ) {
382 if ( strength < 0.5 ) {
383 ship_p->current_max_speed *= fl_sqrt(strength);
387 if ( timestamp_elapsed(ship_p->next_manage_ets) ) {
388 if ( !(objp->flags & OF_PLAYER_SHIP) ) {
390 ship_p->next_manage_ets = timestamp(AI_MODIFY_ETS_INTERVAL);
393 if ( Weapon_energy_cheat ){
394 ship_p->weapon_energy = sinfo_p->max_weapon_reserve;
401 // -------------------------------------------------------------------------------------------------
402 // ai_manage_ets() will determine if a ship should modify it's energy transfer percentages, or
403 // transfer energy from shields->weapons or from weapons->shields
406 // minimum level rule constants
407 #define SHIELDS_MIN_LEVEL_PERCENT 0.3f
408 #define WEAPONS_MIN_LEVEL_PERCENT 0.3f
410 // maximum level rule constants
411 #define SHIELDS_MAX_LEVEL_PERCENT 0.8f
412 #define WEAPONS_MAX_LEVEL_PERCENT 0.8f
414 // emergency rule constants
415 #define SHIELDS_EMERG_LEVEL_PERCENT 0.10f
416 #define WEAPONS_EMERG_LEVEL_PERCENT 0.05f
418 // need this, or ai's tend to totally eliminate engine power!
419 #define MIN_ENGINE_RECHARGE_INDEX 3
421 #define DEFAULT_CHARGE_INDEX 4
422 #define NORMAL_TOLERANCE_PERCENT .10f
424 void ai_manage_ets(object* obj)
426 ship* ship_p = &Ships[obj->instance];
427 ship_info* ship_info_p = &Ship_info[ship_p->ship_info_index];
429 if ( ship_info_p->power_output == 0 )
432 if (ship_p->flags & SF_DYING)
435 // check if any of the three systems are not being used. If so, don't allow energy management.
436 if ( !ship_info_p->shields || !ship_info_p->max_speed || !ship_info_p->max_weapon_reserve)
439 float shield_left_percent = get_shield_strength(obj)/ship_info_p->shields;
440 float weapon_left_percent = ship_p->weapon_energy/ship_info_p->max_weapon_reserve;
442 // maximum level check
443 // MK, changed these, might as well let them go up to 100% if nothing else needs the recharge ability.
444 if ( weapon_left_percent == 1.0f) {
445 decrease_recharge_rate(obj, WEAPONS);
448 if (!(obj->flags & OF_NO_SHIELDS) && (shield_left_percent == 1.0f)) {
449 decrease_recharge_rate(obj, SHIELDS);
454 if (!(obj->flags & OF_NO_SHIELDS) && (shield_left_percent < SHIELDS_MIN_LEVEL_PERCENT)) {
455 if ( weapon_left_percent > WEAPONS_MIN_LEVEL_PERCENT )
456 increase_recharge_rate(obj, SHIELDS);
459 if ( weapon_left_percent < WEAPONS_MIN_LEVEL_PERCENT ) {
460 increase_recharge_rate(obj, WEAPONS);
463 if ( ship_p->engine_recharge_index < MIN_ENGINE_RECHARGE_INDEX ) {
464 increase_recharge_rate(obj, ENGINES);
468 if (!(obj->flags & OF_NO_SHIELDS)) {
469 if ( shield_left_percent < SHIELDS_EMERG_LEVEL_PERCENT ) {
470 if (ship_p->target_shields_delta == 0.0f)
471 transfer_energy_to_shields(obj);
472 } else if ( weapon_left_percent < WEAPONS_EMERG_LEVEL_PERCENT ) {
473 if ( shield_left_percent > SHIELDS_MIN_LEVEL_PERCENT || weapon_left_percent <= 0.01 ) // dampen ai enthusiasm for sucking energy to weapons
474 transfer_energy_to_weapons(obj);
478 // check for return to normal values
479 if ( fl_abs( shield_left_percent - 0.5f ) < NORMAL_TOLERANCE_PERCENT ) {
480 if ( ship_p->shield_recharge_index > DEFAULT_CHARGE_INDEX )
481 decrease_recharge_rate(obj, SHIELDS);
482 else if ( ship_p->shield_recharge_index < DEFAULT_CHARGE_INDEX )
483 increase_recharge_rate(obj, SHIELDS);
488 if ( fl_abs( weapon_left_percent - 0.5f ) < NORMAL_TOLERANCE_PERCENT ) {
489 if ( ship_p->weapon_recharge_index > DEFAULT_CHARGE_INDEX )
490 decrease_recharge_rate(obj, WEAPONS);
491 else if ( ship_p->weapon_recharge_index < DEFAULT_CHARGE_INDEX )
492 increase_recharge_rate(obj, WEAPONS);
496 // -------------------------------------------------------------------------------------------------
497 // hud_show_ets() will display the charge rates for the three systems, and the reserve
498 // energy for shields and weapons. hud_show_ets() is called once per frame.
502 int i, j, index, y_start, y_end, clip_h, w, h, x, y;
504 ship* ship_p = &Ships[Player_obj->instance];
506 if ( Ets_gauge.first_frame < 0 ) {
510 hud_set_gauge_color(HUD_ETS_GAUGE);
512 // draw the letters for the gauges first, before any clipping occurs
514 for ( j = 0; j < 3; j++ ) {
515 if ( j == 1 && Player_obj->flags & OF_NO_SHIELDS ) {
518 Assert(Ets_gauge_info != NULL);
519 gr_printf(Ets_gauge_info[i].letter_coords[0], Ets_gauge_info[i].letter_coords[1], NOX("%c"), Ets_gauge_info[j].letter);
523 // draw the three energy gauges
526 for ( j = 0; j < 3; j++ ) {
529 index = ship_p->weapon_recharge_index;
532 index = ship_p->shield_recharge_index;
533 if ( Player_obj->flags & OF_NO_SHIELDS ) {
538 index = ship_p->engine_recharge_index;
542 clip_h = fl2i( (1 - Energy_levels[index]) * ETS_bar_h[gr_screen.res] );
544 bm_get_info(Ets_gauge.first_frame,&w,&h);
546 if ( index < NUM_ENERGY_LEVELS-1 ) {
547 // some portion of dark needs to be drawn
549 hud_set_gauge_color(HUD_ETS_GAUGE);
551 // draw the top portion
553 Assert(Ets_gauge_info != NULL);
554 x = Ets_gauge_info[i].top_coords[0];
555 y = Ets_gauge_info[i].top_coords[1];
557 GR_AABITMAP_EX(Ets_gauge.first_frame,x,y,w,clip_h,0,0);
559 // draw the bottom portion
560 Assert(Ets_gauge_info != NULL);
561 x = Ets_gauge_info[i].bottom_coords[0];
562 y = Ets_gauge_info[i].bottom_coords[1];
564 y_start = y + (ETS_bar_h[gr_screen.res] - clip_h);
565 y_end = y + ETS_bar_h[gr_screen.res];
567 GR_AABITMAP_EX(Ets_gauge.first_frame, x, y_start, w, y_end-y_start, 0, ETS_bar_h[gr_screen.res]-clip_h);
571 if ( hud_gauge_maybe_flash(HUD_ETS_GAUGE) == 1 ) {
572 hud_set_gauge_color(HUD_ETS_GAUGE, HUD_C_DIM);
573 // hud_set_dim_color();
575 hud_set_gauge_color(HUD_ETS_GAUGE, HUD_C_BRIGHT);
576 // hud_set_bright_color();
578 // some portion of recharge needs to be drawn
580 // draw the top portion
581 Assert(Ets_gauge_info != NULL);
582 x = Ets_gauge_info[i].top_coords[0];
583 y = Ets_gauge_info[i].top_coords[1];
585 y_start = y + clip_h;
586 y_end = y + ETS_bar_h[gr_screen.res];
588 GR_AABITMAP_EX(Ets_gauge.first_frame+1, x, y_start, w, y_end-y_start, 0, clip_h);
590 // draw the bottom portion
591 Assert(Ets_gauge_info != NULL);
592 x = Ets_gauge_info[i].bottom_coords[0];
593 y = Ets_gauge_info[i].bottom_coords[1];
595 GR_AABITMAP_EX(Ets_gauge.first_frame+2, x,y,w,ETS_bar_h[gr_screen.res]-clip_h,0,0);
600 // hud_set_default_color();
603 // -------------------------------------------------------------------------------------------------
604 // set_default_recharge_rates() will set the charge levels for the weapons, shields and
605 // engines to their default levels
606 void set_default_recharge_rates(object* obj)
610 ship* ship_p = &Ships[obj->instance];
611 ship_info* ship_info_p = &Ship_info[ship_p->ship_info_index];
613 if ( ship_info_p->power_output == 0 )
617 if ( ship_info_p->max_weapon_reserve )
618 ship_properties |= HAS_WEAPONS;
620 if (!(obj->flags & OF_NO_SHIELDS))
621 ship_properties |= HAS_SHIELDS;
623 if ( ship_info_p->max_speed )
624 ship_properties |= HAS_ENGINES;
626 // the default charge rate depends on what systems are on each ship
627 switch ( ship_properties ) {
628 case HAS_ENGINES | HAS_WEAPONS | HAS_SHIELDS:
629 ship_p->shield_recharge_index = INTIAL_SHIELD_RECHARGE_INDEX;
630 ship_p->weapon_recharge_index = INTIAL_WEAPON_RECHARGE_INDEX;
631 ship_p->engine_recharge_index = INTIAL_ENGINE_RECHARGE_INDEX;
634 case HAS_ENGINES | HAS_SHIELDS:
635 ship_p->shield_recharge_index = ONE_HALF_INDEX;
636 ship_p->weapon_recharge_index = ZERO_INDEX;
637 ship_p->engine_recharge_index = ONE_HALF_INDEX;
640 case HAS_WEAPONS | HAS_SHIELDS:
641 ship_p->shield_recharge_index = ONE_HALF_INDEX;
642 ship_p->weapon_recharge_index = ONE_HALF_INDEX;
643 ship_p->engine_recharge_index = ZERO_INDEX;
646 case HAS_ENGINES | HAS_WEAPONS:
647 ship_p->shield_recharge_index = ZERO_INDEX;
648 ship_p->weapon_recharge_index = ONE_HALF_INDEX;
649 ship_p->engine_recharge_index = ONE_HALF_INDEX;
653 ship_p->shield_recharge_index = ALL_INDEX;
654 ship_p->weapon_recharge_index = ZERO_INDEX;
655 ship_p->engine_recharge_index = ZERO_INDEX;
659 ship_p->shield_recharge_index = ZERO_INDEX;
660 ship_p->weapon_recharge_index = ZERO_INDEX;
661 ship_p->engine_recharge_index = ALL_INDEX;
665 ship_p->shield_recharge_index = ZERO_INDEX;
666 ship_p->weapon_recharge_index = ALL_INDEX;
667 ship_p->engine_recharge_index = ZERO_INDEX;
671 Int3(); // if no systems, power output should be zero, and this funtion shouldn't be called
676 // -------------------------------------------------------------------------------------------------
677 // increase_recharge_rate() will increase the energy flow to the specified system (one of
678 // WEAPONS, SHIELDS or ENGINES). The increase in energy will result in a decrease to
679 // the other two systems.
680 void increase_recharge_rate(object* obj, SYSTEM_TYPE ship_system)
682 int *gain_index=NULL, *lose_index1=NULL, *lose_index2=NULL, *tmp=NULL;
684 ship *ship_p = &Ships[obj->instance];
686 switch ( ship_system ) {
688 gain_index = &ship_p->weapon_recharge_index;
689 lose_index1 = &ship_p->engine_recharge_index;
690 if ( obj->flags & OF_NO_SHIELDS ) {
693 lose_index2 = &ship_p->shield_recharge_index;
698 if ( obj->flags & OF_NO_SHIELDS ) {
701 gain_index = &ship_p->shield_recharge_index;
702 lose_index1 = &ship_p->weapon_recharge_index;
703 lose_index2 = &ship_p->engine_recharge_index;
707 gain_index = &ship_p->engine_recharge_index;
708 lose_index1 = &ship_p->weapon_recharge_index;
709 if ( obj->flags & OF_NO_SHIELDS ) {
712 lose_index2 = &ship_p->shield_recharge_index;
718 // already full, nothing to do
719 count = MAX_ENERGY_INDEX - *gain_index;
724 if ( obj == Player_obj ) {
725 snd_play( &Snds[SND_ENERGY_TRANS_FAIL], 0.0f );
730 *gain_index += count;
732 // ensure that the highest lose index takes the first decrease
733 if ( lose_index1 && lose_index2 ) {
734 if ( *lose_index1 < *lose_index2 ) {
736 lose_index1 = lose_index2;
743 if ( lose_index1 && *lose_index1 > 0 ) {
751 if ( lose_index2 && *lose_index2 > 0 ) {
756 if ( sanity++ > 10 ) {
762 if ( obj == Player_obj )
763 snd_play( &Snds[SND_ENERGY_TRANS], 0.0f );
766 // -------------------------------------------------------------------------------------------------
767 // decrease_recharge_rate() will decrease the energy flow to the specified system (one of
768 // WEAPONS, SHIELDS or ENGINES). The decrease in energy will result in an increase to
769 // the other two systems.
770 void decrease_recharge_rate(object* obj, SYSTEM_TYPE ship_system)
772 int *lose_index=NULL, *gain_index1=NULL, *gain_index2=NULL, *tmp=NULL;
774 ship *ship_p = &Ships[obj->instance];
776 switch ( ship_system ) {
778 lose_index = &ship_p->weapon_recharge_index;
780 if ( obj->flags & OF_NO_SHIELDS ) {
783 gain_index1 = &ship_p->shield_recharge_index;
786 gain_index2 = &ship_p->engine_recharge_index;
790 if ( obj->flags & OF_NO_SHIELDS ) {
793 lose_index = &ship_p->shield_recharge_index;
794 gain_index1 = &ship_p->weapon_recharge_index;
795 gain_index2 = &ship_p->engine_recharge_index;
799 lose_index = &ship_p->engine_recharge_index;
801 if ( obj->flags & OF_NO_SHIELDS ) {
804 gain_index1 = &ship_p->shield_recharge_index;
807 gain_index2 = &ship_p->weapon_recharge_index;
811 // check how much there is to lose
812 count = min(2, *lose_index);
814 if ( obj == Player_obj ) {
815 snd_play( &Snds[SND_ENERGY_TRANS_FAIL], 0.0f );
820 *lose_index -= count;
822 // make sure that the gain starts with the system which needs it most
823 if ( gain_index1 && gain_index2 ) {
824 if ( *gain_index1 > *gain_index2 ) {
826 gain_index1 = gain_index2;
833 if ( gain_index1 && *gain_index1 < MAX_ENERGY_INDEX ) {
841 if ( gain_index2 && *gain_index2 < MAX_ENERGY_INDEX ) {
846 if ( sanity++ > 10 ) {
852 if ( obj == Player_obj )
853 snd_play( &Snds[SND_ENERGY_TRANS], 0.0f );
856 void transfer_energy_weapon_common(object *objp, float from_field, float to_field, float *from_delta, float *to_delta, float max, float scale)
860 delta = from_field * ENERGY_DIVERT_DELTA * scale;
862 if (to_field + *to_delta + delta > max)
863 delta = max - to_field - *to_delta;
866 if ( objp == Player_obj )
867 snd_play( &Snds[SND_ENERGY_TRANS], 0.0f );
869 if (delta > from_field)
873 *from_delta -= delta;
875 if ( objp == Player_obj )
876 snd_play( &Snds[SND_ENERGY_TRANS_FAIL], 0.0f );
879 // -------------------------------------------------------------------------------------------------
880 // transfer_energy_to_shields() will transfer ENERGY_DIVERT_DELTA percent of weapon energy
882 void transfer_energy_to_shields(object* obj)
884 ship* ship_p = &Ships[obj->instance];
885 ship_info* sinfo_p = &Ship_info[ship_p->ship_info_index];
887 if (ship_p->flags & SF_DYING)
890 if ( obj->flags & OF_NO_SHIELDS ) {
894 transfer_energy_weapon_common(obj, ship_p->weapon_energy, get_shield_strength(obj), &ship_p->target_weapon_energy_delta, &ship_p->target_shields_delta, sinfo_p->shields, 0.5f);
897 // -------------------------------------------------------------------------------------------------
898 // transfer_energy_to_weapons() will transfer ENERGY_DIVERT_DELTA percent of shield energy
900 void transfer_energy_to_weapons(object* obj)
902 ship* ship_p = &Ships[obj->instance];
903 ship_info* sinfo_p = &Ship_info[ship_p->ship_info_index];
905 if (ship_p->flags & SF_DYING)
908 transfer_energy_weapon_common(obj, get_shield_strength(obj), ship_p->weapon_energy, &ship_p->target_shields_delta, &ship_p->target_weapon_energy_delta, sinfo_p->max_weapon_reserve, 1.0f);
911 void hudets_page_in()
913 bm_page_in_aabitmap( Ets_gauge.first_frame, Ets_gauge.num_frames );