// ------------------------------------------------------------------ // hud_shield_equalize() // // Equalize the four shield quadrants for an object // void hud_shield_equalize(object* objp, player* pl) { float strength; int idx; int all_equal; Assert(objp != NULL); if (objp == NULL) return; Assert(pl != NULL); if (pl == NULL) return; Assert(objp->type == OBJ_SHIP); if (objp->type != OBJ_SHIP) return; // Goober5000 - quick out if we have no shields if (objp->flags & OF_NO_SHIELDS) return; // are all quadrants equal? all_equal = 1; for (idx = 0; idx < MAX_SHIELD_SECTIONS - 1; idx++) { if (objp->shield_quadrant[idx] != objp->shield_quadrant[idx + 1]) { all_equal = 0; break; } } if (all_equal) return; strength = shield_get_strength(objp); if (strength == 0.0f) return; // maybe impose a 2% penalty - server side and single player only if (!MULTIPLAYER_CLIENT && (pl->shield_penalty_stamp < 0) || timestamp_elapsed_safe(pl->shield_penalty_stamp, 1000)) { strength *= 0.98f; // reset the penalty timestamp pl->shield_penalty_stamp = timestamp(1000); } shield_set_strength(objp, strength); // beep if (objp == Player_obj) { snd_play(&Snds[SND_SHIELD_XFER_OK]); } }
// ------------------------------------------------------------------------------------------------- // transfer_energy_to_shields() will transfer ENERGY_DIVERT_DELTA percent of weapon energy // to shield energy. void transfer_energy_to_shields(object* obj) { ship* ship_p = &Ships[obj->instance]; if (ship_p->flags & SF_DYING) return; if ( !ship_has_energy_weapons(ship_p) || obj->flags & OF_NO_SHIELDS ) { return; } transfer_energy_weapon_common(obj, ship_p->weapon_energy, shield_get_strength(obj), &ship_p->target_weapon_energy_delta, &ship_p->target_shields_delta, ship_p->ship_max_shield_strength, 0.5f); }
void shield_balance(object *objp, float rate, float penalty) { Assert(objp); if (objp->flags[Object::Object_Flags::No_shields]) { // No shields, bail return; } float shield_hp; shield_hp = shield_get_strength(objp); if (shield_hp == 0.0f) { // Shields are down, bail return; } else if (shield_hp == Ships[objp->instance].ship_max_shield_strength) { // Shields are maxed, bail return; } // Are all quadrants equal? bool all_equal = true; for (int idx = 0; idx < objp->n_quadrants - 1; idx++) { if (objp->shield_quadrant[idx] != objp->shield_quadrant[idx + 1]) { all_equal = false; break; } } if (all_equal) { // Quadrants are equal, bail return; } Assert((rate > 0.0f) && (rate <= 1.0f)); Assert((penalty >= 0.0f) && (penalty <= 1.0f)); float shield_hp_avg = shield_hp / objp->n_quadrants; shield_hp_avg *= 1 - penalty; for (int i = 0; i < objp->n_quadrants; ++i) { if (fabsf(objp->shield_quadrant[i] - shield_hp_avg) < 0.01f) { // Very close, so clamp objp->shield_quadrant[i] = shield_hp_avg; } else { // Else, smoothly balance towards target objp->shield_quadrant[i] += rate * (shield_hp_avg - objp->shield_quadrant[i]); } } }
// ------------------------------------------------------------------------------------------------- // transfer_energy_to_weapons() will transfer ENERGY_DIVERT_DELTA percent of shield energy // to weapon energy. void transfer_energy_to_weapons(object* obj) { ship* ship_p = &Ships[obj->instance]; ship_info* sinfo_p = &Ship_info[ship_p->ship_info_index]; if (ship_p->flags & SF_DYING) return; if ( !ship_has_energy_weapons(ship_p) || obj->flags & OF_NO_SHIELDS ) { return; } transfer_energy_weapon_common(obj, shield_get_strength(obj), ship_p->weapon_energy, &ship_p->target_shields_delta, &ship_p->target_weapon_energy_delta, sinfo_p->max_weapon_reserve, 1.0f); }
/** * Returns true if the shield presents any opposition to something trying to force through it. * * @return If quadrant is -1, looks at entire shield, otherwise just one quadrant */ int ship_is_shield_up( object *obj, int quadrant ) { if ( (quadrant >= 0) && (quadrant < MAX_SHIELD_SECTIONS)) { // Just check one quadrant if (obj->shield_quadrant[quadrant] > MAX(2.0f, 0.1f * get_max_shield_quad(obj))) { return 1; } } else { // Check all quadrants float strength = shield_get_strength(obj); if ( strength > MAX(2.0f*4.0f, 0.1f * Ships[obj->instance].ship_max_shield_strength )) { return 1; } } return 0; // no shield 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 }
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; } } }
// ------------------------------------------------------------------------------------------------- // update_ets() is called once per frame for every OBJ_SHIP in the game. The amount of energy // to send to the weapons and shields is calculated, and the top ship speed is calculated. The // amount of time elapsed from the previous call is passed in as the parameter fl_frametime. // // parameters: obj ==> object that is updating their energy system // fl_frametime ==> game frametime (in seconds) // void update_ets(object* objp, float fl_frametime) { float max_new_shield_energy, max_new_weapon_energy, _ss; if ( fl_frametime <= 0 ){ return; } ship* ship_p = &Ships[objp->instance]; ship_info* sinfo_p = &Ship_info[ship_p->ship_info_index]; float max_g=sinfo_p->max_weapon_reserve, max_s=ship_p->ship_max_shield_strength; if ( ship_p->flags & SF_DYING ){ return; } if ( sinfo_p->power_output == 0 ){ return; } // new_energy = fl_frametime * sinfo_p->power_output; // update weapon energy max_new_weapon_energy = fl_frametime * sinfo_p->max_weapon_regen_per_second * max_g; if ( objp->flags & OF_PLAYER_SHIP ) { ship_p->weapon_energy += Energy_levels[ship_p->weapon_recharge_index] * max_new_weapon_energy * The_mission.ai_profile->weapon_energy_scale[Game_skill_level]; } else { ship_p->weapon_energy += Energy_levels[ship_p->weapon_recharge_index] * max_new_weapon_energy; } if ( ship_p->weapon_energy > sinfo_p->max_weapon_reserve ){ ship_p->weapon_energy = sinfo_p->max_weapon_reserve; } float shield_delta; max_new_shield_energy = fl_frametime * sinfo_p->max_shield_regen_per_second * max_s; if ( objp->flags & OF_PLAYER_SHIP ) { shield_delta = Energy_levels[ship_p->shield_recharge_index] * max_new_shield_energy * The_mission.ai_profile->shield_energy_scale[Game_skill_level]; } else { shield_delta = Energy_levels[ship_p->shield_recharge_index] * max_new_shield_energy; } shield_add_strength(objp, shield_delta); if ( (_ss = shield_get_strength(objp)) > ship_p->ship_max_shield_strength ){ for (int i=0; i<objp->n_quadrants; i++){ objp->shield_quadrant[i] *= ship_p->ship_max_shield_strength / _ss; } } // calculate the top speed of the ship based on the energy flow to engines float y = Energy_levels[ship_p->engine_recharge_index]; ship_p->current_max_speed = ets_get_max_speed(objp, y); // AL 11-15-97: Rules for engine strength affecting max speed: // 1. if strength >= 0.5 no affect // 2. if strength < 0.5 then max_speed = sqrt(strength) // // This will translate to 71% max speed at 50% engines, and 31% max speed at 10% engines // float strength = ship_get_subsystem_strength(ship_p, SUBSYSTEM_ENGINE); // don't let engine strength affect max speed when playing on lowest skill level if ( (objp != Player_obj) || (Game_skill_level > 0) ) { if ( strength < SHIP_MIN_ENGINES_FOR_FULL_SPEED ) { ship_p->current_max_speed *= fl_sqrt(strength); } } if ( timestamp_elapsed(ship_p->next_manage_ets) ) { if ( !(objp->flags & OF_PLAYER_SHIP) ) { ai_manage_ets(objp); ship_p->next_manage_ets = timestamp(AI_MODIFY_ETS_INTERVAL); } else { if ( Weapon_energy_cheat ){ ship_p->weapon_energy = sinfo_p->max_weapon_reserve; } } } }