// Recharge whole shield. // Apply delta/MAX_SHIELD_SECTIONS to each shield section. void shield_add_strength(object* objp, float delta) { // if we aren't going to change anything anyway then just bail if (delta == 0.0f) return; if (!(Ai_info[Ships[objp->instance].ai_index].ai_profile_flags & AIPF_SMART_SHIELD_MANAGEMENT) || delta <= 0.0f) //SUSHI: We don't want smart shield management for negative delta { for (int i = 0; i < MAX_SHIELD_SECTIONS; i++) shield_add_quad(objp, i, delta / MAX_SHIELD_SECTIONS); } else { float section_max = shield_get_max_quad(objp); // smart shield repair while (delta > 0.0f) { //WMC - Set to INT_MAX so that this is set to something float weakest = i2fl(INT_MAX); int weakest_idx = -1; // find weakest shield quadrant for (int i = 0; i < MAX_SHIELD_SECTIONS; i++) { float quad = shield_get_quad(objp, i); if (weakest_idx < 0 || quad < weakest) { weakest = quad; weakest_idx = i; } } // all quads are at full strength if (weakest >= section_max) break; // throw all possible shield power at this quadrant // if there's any left over then apply it to the next weakest on the next pass float xfer_amount; if (weakest + delta > section_max) xfer_amount = section_max - weakest; else xfer_amount = delta; shield_add_quad(objp, weakest_idx, xfer_amount); delta -= xfer_amount; } } }
// Goober5000 void shield_set_quad(object* objp, int quadrant_num, float strength) { // check array bounds Assert(quadrant_num >= 0 && quadrant_num < MAX_SHIELD_SECTIONS); if (quadrant_num < 0 || quadrant_num >= MAX_SHIELD_SECTIONS) return; // check range if (strength < 0.0f) strength = 0.0f; float max_quad = shield_get_max_quad(objp); if (strength > max_quad) strength = max_quad; objp->shield_quadrant[quadrant_num] = strength; }
int shield_is_up(object *objp, int quadrant_num) { Assert(objp); if ((quadrant_num >= 0) && (quadrant_num < objp->n_quadrants)) { // Just check one quadrant float quad = shield_get_quad(objp, quadrant_num); if (quad > MAX(2.0f, 0.1f * shield_get_max_quad(objp))) // [z64555] Where the heck does this 2HP come from? return 1; } else { // Check all quadrants float strength = shield_get_strength(objp); if (strength > MAX(2.0f * objp->n_quadrants, 0.1f * shield_get_max_strength(objp))) // [z64555] Where the heck does this 2HP come from? return 1; } return 0; // no shield strength }
// Returns true if the shield presents any opposition to something // trying to force through it. // If quadrant is -1, looks at entire shield, otherwise // just one quadrant int shield_is_up(object* objp, int quadrant_num) { if ((quadrant_num >= 0) && (quadrant_num < MAX_SHIELD_SECTIONS)) { // Just check one quadrant float quad = shield_get_quad(objp, quadrant_num); if (quad > MAX(2.0f, 0.1f * shield_get_max_quad(objp))) return 1; } else { // Check all quadrants float strength = shield_get_strength(objp); if (strength > MAX(2.0f * MAX_SHIELD_SECTIONS, 0.1f * shield_get_max_strength(objp))) return 1; } return 0; // no shield strength }
// Goober5000 void shield_add_quad(object* objp, int quadrant_num, float delta) { // if we aren't going to change anything anyway then just bail if (delta == 0.0f) return; // check array bounds Assert(quadrant_num >= 0 && quadrant_num < MAX_SHIELD_SECTIONS); if (quadrant_num < 0 || quadrant_num >= MAX_SHIELD_SECTIONS) return; // important: don't use shield_get_quad here float strength = objp->shield_quadrant[quadrant_num] + delta; // check range if (strength < 0.0f) strength = 0.0f; float max_quad = shield_get_max_quad(objp); if (strength > max_quad) strength = max_quad; objp->shield_quadrant[quadrant_num] = strength; }
void shield_add_strength(object *objp, float delta) { Assert(objp); // if we aren't going to change anything anyway then just bail if (delta == 0.0f) return; float shield_str = shield_get_strength(objp); float shield_recharge_limit = shield_get_max_strength(objp); if ((delta > 0.0f) && (shield_str >= shield_recharge_limit)) return; if (!(Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_shield_management]) || delta <= 0.0f) //SUSHI: We don't want smart shield management for negative delta { // set the limit for the shield recharge if ((delta > 0.0f) && ((shield_str + delta) > shield_recharge_limit)) delta = shield_recharge_limit - shield_str; for (int i = 0; i < objp->n_quadrants; i++) shield_add_quad(objp, i, delta / objp->n_quadrants); } else { float section_max = shield_get_max_quad(objp); // smart shield repair while (delta > 0.0f) { //WMC - Set to INT_MAX so that this is set to something float weakest = i2fl(INT_MAX); int weakest_idx = -1; // find weakest shield quadrant for (int i = 0; i < objp->n_quadrants; i++) { float quad = shield_get_quad(objp, i); if (weakest_idx < 0 || quad < weakest) { weakest = quad; weakest_idx = i; } } // all quads are at full strength if (weakest >= section_max) break; // set the limit for the shield recharge if ((delta > 0.0f) && ((shield_str + delta) > shield_recharge_limit)) delta = shield_recharge_limit - shield_str; // throw all possible shield power at this quadrant // if there's any left over then apply it to the next weakest on the next pass float xfer_amount; if (weakest + delta > section_max) xfer_amount = section_max - weakest; else xfer_amount = delta; shield_add_quad(objp, weakest_idx, xfer_amount); delta -= xfer_amount; } } }
void shield_transfer(object *objp, int quadrant, float rate) { Assert(objp); Assert(objp->type == OBJ_SHIP); Assert(quadrant >= 0 && quadrant < objp->n_quadrants); Assert((0.0f < rate) && (rate <= 1.0f)); // The energy to Xfer to the quadrant float xfer_amount = shield_get_max_strength(objp) * rate; // The max amount of energy a quad can have float max_quadrant_val = shield_get_max_quad(objp); if ((objp->shield_quadrant[quadrant] + xfer_amount) > max_quadrant_val) { xfer_amount = max_quadrant_val - objp->shield_quadrant[quadrant]; } Assert(xfer_amount >= 0); if (xfer_amount == 0) { // TODO: provide a feedback sound return; } else if (objp == Player_obj) { snd_play(gamesnd_get_game_sound(SND_SHIELD_XFER_OK)); } float energy_avail = 0.0f; // Energy available from the other quadrants that we can transfer for (int i = 0; i < objp->n_quadrants; i++) { if (i == quadrant) continue; energy_avail += objp->shield_quadrant[i]; } // Percent energy to take from each quadrant float percent_to_take = xfer_amount / energy_avail; if (percent_to_take > 1.0f) { percent_to_take = 1.0f; } for (int i = 0; i < objp->n_quadrants; i++) { float delta; if (i == quadrant) { // Don't take energy from our target continue; } delta = percent_to_take * objp->shield_quadrant[i]; objp->shield_quadrant[i] -= delta; Assert(objp->shield_quadrant[i] >= 0); objp->shield_quadrant[quadrant] += delta; if (objp->shield_quadrant[quadrant] > max_quadrant_val) { // Already reached the max quadrant value. Clamp and bail before losing more any energy. objp->shield_quadrant[quadrant] = max_quadrant_val; break; } } }
void shield_transfer(object *objp, int quadrant, float rate) { Assert(objp); Assert(objp->type == OBJ_SHIP); ship *shipp = &Ships[objp->instance]; ship_info *sip = &Ship_info[shipp->ship_info_index]; if (sip->flags[Ship::Info_Flags::Model_point_shields]) { // Using model point shields, so map to the correct quadrant quadrant = sip->shield_point_augment_ctrls[quadrant]; if (quadrant < 0) { // This quadrant cannot be augmented, bail return; } } Assert(quadrant >= 0 && quadrant < objp->n_quadrants); Assert((0.0f < rate) && (rate <= 1.0f)); // The energy to Xfer to the quadrant float xfer_amount = shield_get_max_strength(objp) * rate; // The max amount of energy a quad can have float max_quadrant_val = shield_get_max_quad(objp); if ((objp->shield_quadrant[quadrant] + xfer_amount) > max_quadrant_val) { xfer_amount = max_quadrant_val - objp->shield_quadrant[quadrant]; } Assert(xfer_amount >= 0); if (xfer_amount == 0) { // TODO: provide a feedback sound return; } else if (objp == Player_obj) { snd_play(&Snds[SND_SHIELD_XFER_OK]); } float energy_avail = 0.0f; // Energy available from the other quadrants that we can transfer for (int i = 0; i < objp->n_quadrants; i++) { if (i == quadrant) continue; energy_avail += objp->shield_quadrant[i]; } // Percent energy to take from each quadrant float percent_to_take = xfer_amount / energy_avail; if (percent_to_take > 1.0f) { percent_to_take = 1.0f; } for (int i = 0; i < objp->n_quadrants; i++) { float delta; if (i == quadrant) { // Don't take energy from our target continue; } delta = percent_to_take * objp->shield_quadrant[i]; objp->shield_quadrant[i] -= delta; Assert(objp->shield_quadrant[i] >= 0); objp->shield_quadrant[quadrant] += delta; if (objp->shield_quadrant[quadrant] > max_quadrant_val) { // Already reached the max quadrant value. Clamp and bail before losing more any energy. objp->shield_quadrant[quadrant] = max_quadrant_val; break; } } }
// Draw the miniature shield icon that is drawn near the reticle void HudGaugeShieldMini::showMiniShields(object *objp) { float max_shield; int hud_color_index, range, frame_offset; int sx, sy, i; if ( objp->type != OBJ_SHIP ) { return; } setGaugeColor(); sx = position[0]+fl2i(HUD_offset_x); sy = position[1]+fl2i(HUD_offset_y); // draw the ship first maybeFlashShield(SHIELD_HIT_TARGET, Shield_hit_data[SHIELD_HIT_TARGET].hull_hit_index); showIntegrity(get_hull_pct(objp)); // draw the four quadrants // Draw shield quadrants at one of NUM_SHIELD_LEVELS max_shield = shield_get_max_quad(objp); for ( i = 0; i < objp->n_quadrants; i++ ) { if ( objp->flags[Object::Object_Flags::No_shields] ) { break; } if ( objp->shield_quadrant[Quadrant_xlate[i]] < 0.1f ) { continue; } if ( maybeFlashShield(SHIELD_HIT_TARGET, i) ) { frame_offset = i+objp->n_quadrants; } else { frame_offset = i; } range = HUD_color_alpha; hud_color_index = fl2i( (objp->shield_quadrant[Quadrant_xlate[i]] / max_shield) * range + 0.5); Assert(hud_color_index >= 0 && hud_color_index <= range); if ( hud_color_index < 0 ) { hud_color_index = 0; } if ( hud_color_index >= HUD_NUM_COLOR_LEVELS ) { hud_color_index = HUD_NUM_COLOR_LEVELS - 1; } if ( maybeFlashSexp() == 1) { // hud_set_bright_color(); setGaugeColor(HUD_C_BRIGHT); } else { // gr_set_color_fast(&HUD_color_defaults[hud_color_index]); setGaugeColor(hud_color_index); } if (frame_offset < Shield_mini_gauge.num_frames) renderBitmap(Shield_mini_gauge.first_frame + frame_offset, sx, sy); } // hud_set_default_color(); }
void HudGaugeShield::showShields(object *objp, int mode) { // static int fod_model = -1; float max_shield; int hud_color_index, range; int sx, sy, i; ship *sp; ship_info *sip; hud_frames *sgp=NULL; if ( objp->type != OBJ_SHIP ) return; // Goober5000 - don't show if primitive sensors if ( Ships[Player_obj->instance].flags[Ship::Ship_Flags::Primitive_sensors] ) return; sp = &Ships[objp->instance]; sip = &Ship_info[sp->ship_info_index]; // bool digitus_improbus = (fod_model != -2 && strstr(sp->ship_name, "Sathanas") != NULL); if ( sip->shield_icon_index == 255 && !(sip->flags[Ship::Info_Flags::Generate_hud_icon]) /*&& !digitus_improbus*/) { return; } setGaugeColor(); // load in shield frames if not already loaded if (sip->shield_icon_index != 255) { sgp = &Shield_gauges.at(sip->shield_icon_index); if ( (sgp->first_frame == -1) && (sip->shield_icon_index < Hud_shield_filenames.size()) ) { sgp->first_frame = bm_load_animation(Hud_shield_filenames.at(sip->shield_icon_index).c_str(), &sgp->num_frames); if (sgp->first_frame == -1) { if (!shield_ani_warning_displayed_already) { shield_ani_warning_displayed_already = true; Warning(LOCATION, "Could not load in the HUD shield ani: %s\n", Hud_shield_filenames.at(sip->shield_icon_index).c_str()); } return; } } } sx = position[0]; sy = position[1]; sx += fl2i(HUD_offset_x); sy += fl2i(HUD_offset_y); // draw the ship first maybeFlashShield(SHIELD_HIT_PLAYER, Shield_hit_data[SHIELD_HIT_PLAYER].hull_hit_index); if(sip->shield_icon_index != 255) { renderBitmap(sgp->first_frame, sx, sy); } else { bool g3_yourself = !g3_in_frame(); angles rot_angles = {-1.570796327f,0.0f,0.0f}; matrix object_orient; vm_angles_2_matrix(&object_orient, &rot_angles); gr_screen.clip_width = 112; gr_screen.clip_height = 93; //Fire it up if(g3_yourself) g3_start_frame(1); hud_save_restore_camera_data(1); setClip(sx, sy, 112, 93); //if(!digitus_improbus) g3_set_view_matrix( &sip->closeup_pos, &vmd_identity_matrix, sip->closeup_zoom * 2.5f); /*else { vec3d finger_vec = {0.0f, 0.0f, 176.0f}; g3_set_view_matrix( &finger_vec, &vmd_identity_matrix, 1.0f); }*/ gr_set_proj_matrix(0.5f*Proj_fov, gr_screen.clip_aspect, Min_draw_distance, Max_draw_distance); gr_set_view_matrix(&Eye_position, &Eye_matrix); //We're ready to show stuff //if(!digitus_improbus) { model_render_params render_info; render_info.set_flags(MR_NO_LIGHTING | MR_AUTOCENTER | MR_NO_FOGGING); render_info.set_replacement_textures(sp->ship_replacement_textures); render_info.set_detail_level_lock(1); render_info.set_object_number(OBJ_INDEX(objp)); model_render_immediate( &render_info, sip->model_num, &object_orient, &vmd_zero_vector ); } /*else { if(fod_model == -1) { fod_model = model_load(NOX("FoD.pof"), 0, NULL); if(fod_model == -1) { fod_model = -2; return; } } model_render(fod_model, &object_orient, &vmd_zero_vector, MR_NO_LIGHTING | MR_LOCK_DETAIL | MR_AUTOCENTER | MR_NO_FOGGING, -1, -1); }*/ //We're done gr_end_view_matrix(); gr_end_proj_matrix(); if(g3_yourself) g3_end_frame(); hud_save_restore_camera_data(0); resetClip(); } if(!sip->max_shield_strength) return; // draw the quadrants // // Draw shield quadrants at one of NUM_SHIELD_LEVELS max_shield = shield_get_max_quad(objp); coord2d shield_icon_coords[6]; for ( i = 0; i < objp->n_quadrants; i++ ) { if ( objp->flags[Object::Object_Flags::No_shields] ) { break; } if ( !(sip->flags[Ship::Info_Flags::Model_point_shields]) ) { if ( objp->shield_quadrant[Quadrant_xlate[i]] < 0.1f ) continue; } else { if ( objp->shield_quadrant[i] < 0.1f ) continue; } range = MAX(HUD_COLOR_ALPHA_MAX, HUD_color_alpha + objp->n_quadrants); if ( !(sip->flags[Ship::Info_Flags::Model_point_shields]) ) hud_color_index = fl2i( (objp->shield_quadrant[Quadrant_xlate[i]] / max_shield) * range); else hud_color_index = fl2i( (objp->shield_quadrant[i] / max_shield) * range); Assert(hud_color_index >= 0 && hud_color_index <= range); if ( hud_color_index < 0 ) { hud_color_index = 0; } if ( hud_color_index >= HUD_NUM_COLOR_LEVELS ) { hud_color_index = HUD_NUM_COLOR_LEVELS - 1; } int flash=0; flash = maybeFlashShield(mode, i); if ( !flash ) { // gr_set_color_fast(&HUD_color_defaults[hud_color_index]); setGaugeColor(hud_color_index); if(sip->shield_icon_index != 255) { int framenum = sgp->first_frame+i+1; if (framenum < sgp->first_frame+sgp->num_frames) renderBitmap(framenum, sx, sy); } else { //Ugh, draw four shield quadrants static const int TRI_EDGE = 6; static const int BAR_LENGTH = 112; static const int BAR_HEIGHT = 54; static const int BAR_WIDTH = 6; static const int SHIELD_OFFSET = BAR_WIDTH + TRI_EDGE + 3; switch(i) { //Top case 0: shield_icon_coords[0].x = sx; shield_icon_coords[0].y = sy+BAR_WIDTH+TRI_EDGE; shield_icon_coords[1].x = sx; shield_icon_coords[1].y = sy; shield_icon_coords[2].x = sx+TRI_EDGE; shield_icon_coords[2].y = sy+BAR_WIDTH; shield_icon_coords[3].x = sx+BAR_LENGTH; shield_icon_coords[3].y = sy; shield_icon_coords[4].x = sx+BAR_LENGTH-TRI_EDGE; shield_icon_coords[4].y = sy+BAR_WIDTH; shield_icon_coords[5].x = sx+BAR_LENGTH; shield_icon_coords[5].y = sy+BAR_WIDTH+TRI_EDGE; renderShieldIcon(shield_icon_coords); break; //Left case 3: sy += SHIELD_OFFSET; shield_icon_coords[0].x = sx+BAR_WIDTH+TRI_EDGE; shield_icon_coords[0].y = sy+BAR_HEIGHT; shield_icon_coords[1].x = sx; shield_icon_coords[1].y = sy+BAR_HEIGHT; shield_icon_coords[2].x = sx+BAR_WIDTH; shield_icon_coords[2].y = sy+BAR_HEIGHT-TRI_EDGE; shield_icon_coords[3].x = sx; shield_icon_coords[3].y = sy; shield_icon_coords[4].x = sx+BAR_WIDTH; shield_icon_coords[4].y = sy+TRI_EDGE; shield_icon_coords[5].x = sx+BAR_WIDTH+TRI_EDGE; shield_icon_coords[5].y = sy; renderShieldIcon(shield_icon_coords); sy -= SHIELD_OFFSET + BAR_WIDTH + TRI_EDGE; break; //Right case 1: sx += BAR_LENGTH; sy += SHIELD_OFFSET; shield_icon_coords[0].x = sx-BAR_WIDTH-TRI_EDGE; shield_icon_coords[0].y = sy; shield_icon_coords[1].x = sx; shield_icon_coords[1].y = sy; shield_icon_coords[2].x = sx-BAR_WIDTH; shield_icon_coords[2].y = sy+TRI_EDGE; shield_icon_coords[3].x = sx; shield_icon_coords[3].y = sy+BAR_HEIGHT; shield_icon_coords[4].x = sx-BAR_WIDTH; shield_icon_coords[4].y = sy+BAR_HEIGHT-TRI_EDGE; shield_icon_coords[5].x = sx-BAR_WIDTH-TRI_EDGE; shield_icon_coords[5].y = sy+BAR_HEIGHT; renderShieldIcon(shield_icon_coords); sx -= BAR_LENGTH; sy -= SHIELD_OFFSET; break; //Bottom case 2: sy += BAR_HEIGHT + SHIELD_OFFSET*2 - BAR_WIDTH - TRI_EDGE; shield_icon_coords[0].x = sx+BAR_LENGTH; shield_icon_coords[0].y = sy; shield_icon_coords[1].x = sx+BAR_LENGTH; shield_icon_coords[1].y = sy+BAR_WIDTH+TRI_EDGE; shield_icon_coords[2].x = sx+BAR_LENGTH-TRI_EDGE; shield_icon_coords[2].y = sy+TRI_EDGE; shield_icon_coords[3].x = sx; shield_icon_coords[3].y = sy+BAR_WIDTH+TRI_EDGE; shield_icon_coords[4].x = sx+TRI_EDGE; shield_icon_coords[4].y = sy+TRI_EDGE; shield_icon_coords[5].x = sx; shield_icon_coords[5].y = sy; renderShieldIcon(shield_icon_coords); sy -= BAR_HEIGHT + SHIELD_OFFSET*2 - BAR_WIDTH - TRI_EDGE; break; //Whoops? default: nprintf(("HUD", "Invalid shield quadrant %d specified!\n", i)); break; } } } } // hud_set_default_color(); }
// Draw the miniature shield icon that is drawn near the reticle // this function is only used by multi_ingame_join_display_ship() in multi_ingame.cpp as of the new HudGauge implementation (Swifty) void hud_shield_show_mini(object *objp, int x_force, int y_force, int x_hull_offset, int y_hull_offset) { float max_shield; int hud_color_index, range, frame_offset; int sx, sy, i; if ( objp->type != OBJ_SHIP ) { return; } hud_set_gauge_color(HUD_TARGET_MINI_ICON); if (!Shield_mini_loaded) return; sx = (x_force == -1) ? Shield_mini_coords[gr_screen.res][0]+fl2i(HUD_offset_x) : x_force; sy = (y_force == -1) ? Shield_mini_coords[gr_screen.res][1]+fl2i(HUD_offset_y) : y_force; // draw the ship first hud_shield_maybe_flash(HUD_TARGET_MINI_ICON, SHIELD_HIT_TARGET, Shield_hit_data[SHIELD_HIT_TARGET].hull_hit_index); hud_show_mini_ship_integrity(objp, x_force + x_hull_offset,y_force + y_hull_offset); // draw the four quadrants // Draw shield quadrants at one of NUM_SHIELD_LEVELS max_shield = shield_get_max_quad(objp); for ( i = 0; i < objp->n_quadrants; i++ ) { if ( objp->flags[Object::Object_Flags::No_shields] || i >= DEFAULT_SHIELD_SECTIONS) { break; } if (objp->shield_quadrant[Quadrant_xlate[i]] < 0.1f ) { continue; } if ( hud_shield_maybe_flash(HUD_TARGET_MINI_ICON, SHIELD_HIT_TARGET, i) ) { frame_offset = i+objp->n_quadrants; } else { frame_offset = i; } range = HUD_color_alpha; hud_color_index = fl2i( (objp->shield_quadrant[Quadrant_xlate[i]] / max_shield) * range + 0.5); Assert(hud_color_index >= 0 && hud_color_index <= range); if ( hud_color_index < 0 ) { hud_color_index = 0; } if ( hud_color_index >= HUD_NUM_COLOR_LEVELS ) { hud_color_index = HUD_NUM_COLOR_LEVELS - 1; } if ( hud_gauge_maybe_flash(HUD_TARGET_MINI_ICON) == 1) { // hud_set_bright_color(); hud_set_gauge_color(HUD_TARGET_MINI_ICON, HUD_C_BRIGHT); } else { // gr_set_color_fast(&HUD_color_defaults[hud_color_index]); hud_set_gauge_color(HUD_TARGET_MINI_ICON, hud_color_index); } GR_AABITMAP(Shield_mini_gauge.first_frame + frame_offset, sx + HUD_nose_x, sy + HUD_nose_y); } // hud_set_default_color(); }