mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 08:15:59 -10:00
Add an "On Ship Damage" script hook (#7894)
* Add an "On Ship Damage" script hook Runs after resolved damage has been applied to a ship (lethal hits run before the destruction callback). Hook variables: Target, Source, Attacker, WeaponClass, WeaponSubtype, SourceKind (PROJECTILE, BEAM, SHOCKWAVE, COLLISION, OTHER), DamageType, ShieldDamage, HullDamage, Quadrant, Ballistic, BeamWeapon and LethalHit. Conditions can filter on the target ship. Nothing is computed unless a script has registered the hook. * Move the On Ship Damage hook call out of a lambda ship_do_damage() now calls a file-level static function, ship_run_damage_hook(), that takes the values it needs as arguments instead of capturing the function state. Hook behaviour is unchanged. * Report subsystem damage in the On Ship Damage hook Adds SubsystemDamage, the total subsystem strength a damage application removed, so a hit absorbed by subsystems no longer looks like a small hull hit. The hook description now says it only runs where damage is applied, which excludes multiplayer clients. * Address On Ship Damage review comments - Remove WeaponClass, WeaponSubtype, Ballistic and BeamWeapon from the hook. Scripts read these from Source when it is a weapon. - Add a "Weapon class" condition for the On Ship Damage hook. It matches only when the damage source is a weapon of that class; a weapon name that does not exist never matches. - SubsystemDamage is now a table keyed by subsystem handle that lists only the subsystems that lost strength. The total is removed. - Rename PROJECTILE to NON_BEAM_WEAPON. - Classify SourceKind by damage source: COLLISION for ship, debris and asteroid collisions; EXPLOSION for ship-death and docked-ship blasts and asteroid blasts; WASH for engine wash; SELF for kills where the ship damages itself; OTHER for other ship-sourced damage. - Reword the hook description. * Key On Ship Damage SubsystemDamage by canonical name Lua tables cannot use subsystem handles as keys in a usable way, so key the SubsystemDamage table by each subsystem's CanonicalName instead. * Tag ship-vs-prop damage as a collision and use in_bounds The ship-vs-prop collision call didn't pass DamageSource::Collision, so the On Ship Damage hook reported those hits as OTHER. Every other collision path was already tagged. Also use SCP_vector::in_bounds() for the Weapon_info and Damage_types index checks in ship_run_damage_hook().
This commit is contained in:
1 parent
4dc0ca7878
commit
49464c56f6
10 files changed
+188
-18
No files matched your search
@@ -1693,7 +1693,7 @@ static void asteroid_do_area_effect(object *asteroid_objp)
|
||||
if ( weapon_area_calc_damage(ship_objp, &asteroid_objp->pos, asip->inner_rad, asip->outer_rad, asip->blast, asip->damage, &blast, &damage, asip->outer_rad) == -1 )
|
||||
continue;
|
||||
|
||||
ship_apply_global_damage(ship_objp, asteroid_objp, &asteroid_objp->pos, damage, asip->damage_type_idx);
|
||||
ship_apply_global_damage(ship_objp, asteroid_objp, &asteroid_objp->pos, damage, asip->damage_type_idx, DamageSource::Explosion);
|
||||
weapon_area_apply_blast(nullptr, ship_objp, &asteroid_objp->pos, blast, false);
|
||||
} // end for
|
||||
}
|
||||
|
||||
@@ -158,12 +158,12 @@ int collide_debris_ship( obj_pair * pair )
|
||||
quadrant_num = -1;
|
||||
}
|
||||
if (apply_ship_damage) {
|
||||
ship_apply_local_damage(debris_hit_info.heavy, debris_hit_info.light, &hitpos, ship_damage, Debris[debris_objp->instance].damage_type_idx, quadrant_num, CREATE_SPARKS, debris_hit_info.heavy_submodel_num);
|
||||
ship_apply_local_damage(debris_hit_info.heavy, debris_hit_info.light, &hitpos, ship_damage, Debris[debris_objp->instance].damage_type_idx, quadrant_num, CREATE_SPARKS, debris_hit_info.heavy_submodel_num, nullptr, 1.f, nullptr, DamageSource::Collision);
|
||||
}
|
||||
} else {
|
||||
// don't draw sparks using sphere hit position
|
||||
if (apply_ship_damage) {
|
||||
ship_apply_local_damage(debris_hit_info.light, debris_hit_info.heavy, &hitpos, ship_damage, Debris[debris_objp->instance].damage_type_idx, MISS_SHIELDS, NO_SPARKS);
|
||||
ship_apply_local_damage(debris_hit_info.light, debris_hit_info.heavy, &hitpos, ship_damage, Debris[debris_objp->instance].damage_type_idx, MISS_SHIELDS, NO_SPARKS, -1, nullptr, 1.f, nullptr, DamageSource::Collision);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,10 +348,10 @@ int collide_asteroid_ship( obj_pair * pair )
|
||||
(ship_objp->flags[Object::Object_Flags::No_shields]) || !ship_is_shield_up(ship_objp, quadrant_num) ) {
|
||||
quadrant_num = -1;
|
||||
}
|
||||
ship_apply_local_damage(asteroid_hit_info.heavy, asteroid_hit_info.light, &hitpos, ship_damage, ast_damage_type, quadrant_num, CREATE_SPARKS, asteroid_hit_info.heavy_submodel_num);
|
||||
ship_apply_local_damage(asteroid_hit_info.heavy, asteroid_hit_info.light, &hitpos, ship_damage, ast_damage_type, quadrant_num, CREATE_SPARKS, asteroid_hit_info.heavy_submodel_num, nullptr, 1.f, nullptr, DamageSource::Collision);
|
||||
} else {
|
||||
// don't draw sparks (using sphere hitpos)
|
||||
ship_apply_local_damage(asteroid_hit_info.light, asteroid_hit_info.heavy, &hitpos, ship_damage, ast_damage_type, MISS_SHIELDS, NO_SPARKS);
|
||||
ship_apply_local_damage(asteroid_hit_info.light, asteroid_hit_info.heavy, &hitpos, ship_damage, ast_damage_type, MISS_SHIELDS, NO_SPARKS, -1, nullptr, 1.f, nullptr, DamageSource::Collision);
|
||||
}
|
||||
|
||||
// maybe print Collision on HUD
|
||||
|
||||
@@ -1392,14 +1392,14 @@ void collide_ship_ship_process(obj_pair * pair, const std::any& collision_data)
|
||||
|
||||
float damage_heavy = (100.0f * damage / heavy_obj->phys_info.mass);
|
||||
ship_apply_local_damage(ship_ship_hit_info.heavy, ship_ship_hit_info.light, &world_hit_pos, damage_heavy, light_shipp->collision_damage_type_idx,
|
||||
quadrant_num, CREATE_SPARKS, ship_ship_hit_info.heavy_submodel_num, &ship_ship_hit_info.collision_normal);
|
||||
quadrant_num, CREATE_SPARKS, ship_ship_hit_info.heavy_submodel_num, &ship_ship_hit_info.collision_normal, 1.f, nullptr, DamageSource::Collision);
|
||||
|
||||
hud_shield_quadrant_hit(ship_ship_hit_info.heavy, quadrant_num);
|
||||
|
||||
// don't draw sparks (using sphere hitpos)
|
||||
float damage_light = (100.0f * damage / light_obj->phys_info.mass);
|
||||
ship_apply_local_damage(ship_ship_hit_info.light, ship_ship_hit_info.heavy, &world_hit_pos, damage_light, heavy_shipp->collision_damage_type_idx,
|
||||
MISS_SHIELDS, NO_SPARKS, -1, &ship_ship_hit_info.collision_normal);
|
||||
MISS_SHIELDS, NO_SPARKS, -1, &ship_ship_hit_info.collision_normal, 1.f, nullptr, DamageSource::Collision);
|
||||
|
||||
hud_shield_quadrant_hit(ship_ship_hit_info.light, -1);
|
||||
|
||||
@@ -1811,7 +1811,7 @@ int collide_prop_ship(obj_pair* pair)
|
||||
|
||||
// don't draw sparks (using sphere hitpos)
|
||||
damage = (100.0f * damage / ship_objp->phys_info.mass);
|
||||
ship_apply_local_damage(ship_objp, prop_objp, &world_hit_pos, damage, -1, MISS_SHIELDS, CREATE_SPARKS, -1, &prop_ship_hit_info.collision_normal);
|
||||
ship_apply_local_damage(ship_objp, prop_objp, &world_hit_pos, damage, -1, MISS_SHIELDS, CREATE_SPARKS, -1, &prop_ship_hit_info.collision_normal, 1.f, nullptr, DamageSource::Collision);
|
||||
|
||||
hud_shield_quadrant_hit(ship_objp, -1);
|
||||
}
|
||||
|
||||
@@ -559,6 +559,22 @@ const std::shared_ptr<Hook<>> OnCameraSetUpHook = Hook<>::Factory("On Camera Set
|
||||
{"Camera", "camera", "The camera about to be used for rendering."},
|
||||
});
|
||||
|
||||
const std::shared_ptr<Hook<ShipDamageConditions>> OnShipDamage = Hook<ShipDamageConditions>::Factory(
|
||||
"On Ship Damage", "Called after damage is applied to a ship; lethal hits run before the On Ship Death Started hook. "
|
||||
"Only called where damage is applied: in single player and on a multiplayer server, not on multiplayer clients.",
|
||||
{
|
||||
{"Target", "ship", "The ship that took the damage."},
|
||||
{"Source", "object", "The weapon, beam, shockwave, or other object that caused the damage. Could be nil."},
|
||||
{"Attacker", "object", "The source ship or parent object, if available."},
|
||||
{"SourceKind", "string", "NON_BEAM_WEAPON, BEAM, SHOCKWAVE, COLLISION, EXPLOSION, WASH, SELF (the ship damaged itself, such as a self-destruct), or OTHER."},
|
||||
{"DamageType", "string", "The damage type, or UNKNOWN if none is defined."},
|
||||
{"ShieldDamage", "number", "Actual total shield strength removed by this damage application."},
|
||||
{"HullDamage", "number", "Actual hull strength removed, clamped to the target's remaining hull."},
|
||||
{"SubsystemDamage", "table", "Maps each subsystem's CanonicalName to the strength it lost in this damage application. Only subsystems that lost strength are listed, in no particular order."},
|
||||
{"Quadrant", "number", "Shield quadrant hit, or -1 when no single quadrant applies."},
|
||||
{"LethalHit", "boolean", "Whether this hit reduced positive hull strength to zero or below."},
|
||||
});
|
||||
|
||||
// ========== FRED HOOKS ==========
|
||||
|
||||
const std::shared_ptr<Hook<>> FredOnMissionLoad = Hook<>::Factory("FRED On Mission Load",
|
||||
|
||||
@@ -100,6 +100,8 @@ extern const std::shared_ptr<Hook<>> OnStateAboutToEndHook;
|
||||
extern const std::shared_ptr<OverridableHook<>> OnStateEndHook;
|
||||
extern const std::shared_ptr<Hook<>> OnCameraSetUpHook;
|
||||
|
||||
extern const std::shared_ptr<Hook<ShipDamageConditions>> OnShipDamage;
|
||||
|
||||
// FRED Hooks
|
||||
extern const std::shared_ptr<Hook<>> FredOnMissionLoad;
|
||||
extern const std::shared_ptr<Hook<>> FredOnMissionSpecsSave;
|
||||
|
||||
@@ -232,6 +232,18 @@ HOOK_CONDITIONS_START(ShipDeathConditions)
|
||||
HOOK_CONDITION_SHIPP(ShipDeathConditions, "", "that died.", dying_shipp);
|
||||
HOOK_CONDITIONS_END
|
||||
|
||||
// Damage with no weapon has weapon_info_index -1, and so does a weapon name that does not exist, so a named weapon
|
||||
// class must also be a real weapon to match.
|
||||
static bool conditionDamageWeaponClassMatches(int damage_weapon_index, const int& weapon_index)
|
||||
{
|
||||
return damage_weapon_index >= 0 && damage_weapon_index == weapon_index;
|
||||
}
|
||||
|
||||
HOOK_CONDITIONS_START(ShipDamageConditions)
|
||||
HOOK_CONDITION_SHIPP(ShipDamageConditions, "Target ", "that took damage.", target_shipp);
|
||||
HOOK_CONDITION(ShipDamageConditions, "Weapon class", "Specifies the class of the weapon that caused the damage. For a shockwave, this is the weapon that created it.", weapon_info_index, conditionParseWeaponClass, conditionDamageWeaponClassMatches);
|
||||
HOOK_CONDITIONS_END
|
||||
|
||||
HOOK_CONDITIONS_START(SubsystemDeathConditions)
|
||||
HOOK_CONDITION_SHIPP(SubsystemDeathConditions, "", "whose subsystem got destroyed.", affected_shipp);
|
||||
HOOK_CONDITIONS_END
|
||||
|
||||
@@ -63,6 +63,12 @@ struct ShipDeathConditions {
|
||||
const ship* dying_shipp;
|
||||
};
|
||||
|
||||
struct ShipDamageConditions {
|
||||
HOOK_DEFINE_CONDITIONS;
|
||||
const ship* target_shipp;
|
||||
int weapon_info_index; // the weapon that caused the damage, or -1 if none
|
||||
};
|
||||
|
||||
struct SubsystemDeathConditions {
|
||||
HOOK_DEFINE_CONDITIONS;
|
||||
const ship* affected_shipp;
|
||||
|
||||
+2
-2
@@ -9330,7 +9330,7 @@ static void ship_blow_up_area_apply_blast( object *exp_objp)
|
||||
|
||||
switch ( objp->type ) {
|
||||
case OBJ_SHIP:
|
||||
ship_apply_global_damage( objp, exp_objp, &exp_objp->pos, damage, sip->shockwave.damage_type_idx);
|
||||
ship_apply_global_damage( objp, exp_objp, &exp_objp->pos, damage, sip->shockwave.damage_type_idx, DamageSource::Explosion);
|
||||
ship_apply_whack( &force, &exp_objp->pos, objp );
|
||||
break;
|
||||
case OBJ_ASTEROID:
|
||||
@@ -9387,7 +9387,7 @@ static void do_dying_undock_physics(object *dying_objp, ship *dying_shipp)
|
||||
float docked_mass = dying_objp->phys_info.mass + docked_objp->phys_info.mass;
|
||||
|
||||
// damage this docked object
|
||||
ship_apply_global_damage(docked_objp, dying_objp, &dying_objp->pos, damage, -1);
|
||||
ship_apply_global_damage(docked_objp, dying_objp, &dying_objp->pos, damage, -1, DamageSource::Explosion);
|
||||
|
||||
// do physics
|
||||
vm_vec_sub(&impulse_norm, &docked_objp->pos, &dying_objp->pos);
|
||||
|
||||
+132
-6
@@ -2393,6 +2393,112 @@ static int maybe_shockwave_damage_adjust(const object *ship_objp, const object *
|
||||
return 1;
|
||||
}
|
||||
|
||||
// The shield, hull and per-subsystem strength of a ship, recorded before a ship_do_damage() call. Only filled in while
|
||||
// the On Ship Damage hook is active.
|
||||
struct ship_damage_snapshot {
|
||||
float hull_strength = 0.0f;
|
||||
float shield_strength = 0.0f;
|
||||
SCP_vector<std::pair<ship_subsys *, float>> subsystem_hits;
|
||||
};
|
||||
|
||||
static void ship_take_damage_snapshot(object *ship_objp, ship_damage_snapshot &snapshot)
|
||||
{
|
||||
ship *shipp = &Ships[ship_objp->instance];
|
||||
snapshot.hull_strength = ship_objp->hull_strength;
|
||||
snapshot.shield_strength = shield_get_strength(ship_objp);
|
||||
snapshot.subsystem_hits.clear();
|
||||
for (ship_subsys *subsys = GET_FIRST(&shipp->subsys_list); subsys != END_OF_LIST(&shipp->subsys_list); subsys = GET_NEXT(subsys)) {
|
||||
snapshot.subsystem_hits.emplace_back(subsys, subsys->current_hits);
|
||||
}
|
||||
}
|
||||
|
||||
// Runs the On Ship Damage hook for one ship_do_damage() call, reporting what the ship lost since the snapshot.
|
||||
// Does nothing if the ship lost none of its shield, hull or subsystem strength.
|
||||
static void ship_run_damage_hook(object *ship_objp, object *other_obj, int weapon_info_index, int damage_type_idx, int quadrant, DamageSource source, bool wash_damage, const ship_damage_snapshot &before)
|
||||
{
|
||||
const float shield_damage = MAX(0.0f, before.shield_strength - shield_get_strength(ship_objp));
|
||||
const float hull_damage = MAX(0.0f, MAX(0.0f, before.hull_strength) - MAX(0.0f, ship_objp->hull_strength));
|
||||
|
||||
bool subsystem_hit = false;
|
||||
for (const auto &entry : before.subsystem_hits) {
|
||||
if (entry.first->current_hits < entry.second) {
|
||||
subsystem_hit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shield_damage <= 0.0f && hull_damage <= 0.0f && !subsystem_hit) {
|
||||
return;
|
||||
}
|
||||
const bool lethal_hit = before.hull_strength > 0.0f && ship_objp->hull_strength <= 0.0f;
|
||||
|
||||
// the subsystems that lost strength, keyed by canonical subsystem name
|
||||
luacpp::LuaTable subsystem_losses = luacpp::LuaTable::create(Script_system.GetLuaSession());
|
||||
for (const auto &entry : before.subsystem_hits) {
|
||||
const float lost = entry.second - entry.first->current_hits;
|
||||
if (lost > 0.0f) {
|
||||
subsystem_losses.addValue(ship_subsys_get_canonical_name(entry.first), lost);
|
||||
}
|
||||
}
|
||||
|
||||
const weapon_info *wip = Weapon_info.in_bounds(weapon_info_index) ? &Weapon_info[weapon_info_index] : nullptr;
|
||||
if (!Damage_types.in_bounds(damage_type_idx) && wip != nullptr) {
|
||||
damage_type_idx = wip->damage_type_idx;
|
||||
}
|
||||
const char *damage_type = Damage_types.in_bounds(damage_type_idx) ? Damage_types[damage_type_idx].name : "UNKNOWN";
|
||||
|
||||
const char *source_kind = "OTHER";
|
||||
if (source == DamageSource::Collision) {
|
||||
source_kind = "COLLISION";
|
||||
} else if (source == DamageSource::Explosion) {
|
||||
source_kind = "EXPLOSION";
|
||||
} else if (wash_damage) {
|
||||
source_kind = "WASH";
|
||||
} else if (other_obj == ship_objp) {
|
||||
source_kind = "SELF";
|
||||
} else if (other_obj != nullptr) {
|
||||
switch (other_obj->type) {
|
||||
case OBJ_WEAPON:
|
||||
source_kind = "NON_BEAM_WEAPON";
|
||||
break;
|
||||
case OBJ_BEAM:
|
||||
source_kind = "BEAM";
|
||||
break;
|
||||
case OBJ_SHOCKWAVE:
|
||||
source_kind = "SHOCKWAVE";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
object *attacker_objp = nullptr;
|
||||
if (other_obj != nullptr) {
|
||||
if (other_obj->type == OBJ_BEAM) {
|
||||
int parent_objnum = beam_get_parent(other_obj);
|
||||
if (parent_objnum >= 0) {
|
||||
attacker_objp = &Objects[parent_objnum];
|
||||
}
|
||||
} else if (other_obj->type == OBJ_SHIP) {
|
||||
attacker_objp = other_obj;
|
||||
} else if (other_obj->parent >= 0 && other_obj->parent < MAX_OBJECTS && Objects[other_obj->parent].signature == other_obj->parent_sig) {
|
||||
attacker_objp = &Objects[other_obj->parent];
|
||||
}
|
||||
}
|
||||
|
||||
scripting::hooks::OnShipDamage->run(scripting::hooks::ShipDamageConditions{ &Ships[ship_objp->instance], weapon_info_index },
|
||||
scripting::hook_param_list(
|
||||
scripting::hook_param("Target", 'o', ship_objp),
|
||||
scripting::hook_param("Source", 'o', other_obj, other_obj != nullptr),
|
||||
scripting::hook_param("Attacker", 'o', attacker_objp, attacker_objp != nullptr),
|
||||
scripting::hook_param("SourceKind", 's', source_kind),
|
||||
scripting::hook_param("DamageType", 's', damage_type),
|
||||
scripting::hook_param("ShieldDamage", 'f', shield_damage),
|
||||
scripting::hook_param("HullDamage", 'f', hull_damage),
|
||||
scripting::hook_param("SubsystemDamage", 't', subsystem_losses),
|
||||
scripting::hook_param("Quadrant", 'i', quadrant),
|
||||
scripting::hook_param("LethalHit", 'b', lethal_hit)));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ship_do_damage()
|
||||
//
|
||||
@@ -2411,7 +2517,7 @@ static int maybe_shockwave_damage_adjust(const object *ship_objp, const object *
|
||||
// Goober5000 - sanity checked this whole function in the case that other_obj is NULL, which
|
||||
// will happen with the explosion-effect sexp
|
||||
void ai_update_lethality(const object *ship_objp, const object *weapon_obj, float damage);
|
||||
static void ship_do_damage(object *ship_objp, object *other_obj, const vec3d *hitpos, float damage, int quadrant, int submodel_num, int damage_type_idx = -1, bool wash_damage = false, float hit_dot = 1.f, const vec3d* hit_normal = nullptr, const vec3d* local_hitpos = nullptr)
|
||||
static void ship_do_damage(object *ship_objp, object *other_obj, const vec3d *hitpos, float damage, int quadrant, int submodel_num, int damage_type_idx = -1, bool wash_damage = false, float hit_dot = 1.f, const vec3d* hit_normal = nullptr, const vec3d* local_hitpos = nullptr, DamageSource source = DamageSource::Inferred)
|
||||
{
|
||||
// mprintf(("doing damage\n"));
|
||||
|
||||
@@ -2426,6 +2532,13 @@ static void ship_do_damage(object *ship_objp, object *other_obj, const vec3d *hi
|
||||
|
||||
Assertion(ship_objp->instance >= 0 && ship_objp->type == OBJ_SHIP, "invalid ship target in ship_do_damage");
|
||||
shipp = &Ships[ship_objp->instance];
|
||||
// snapshot for the On Ship Damage hook, which reports what the ship actually lost
|
||||
const bool damage_hook_active = scripting::hooks::OnShipDamage->isActive();
|
||||
bool damage_hook_ran = false;
|
||||
ship_damage_snapshot damage_before;
|
||||
if (damage_hook_active) {
|
||||
ship_take_damage_snapshot(ship_objp, damage_before);
|
||||
}
|
||||
|
||||
// maybe adjust damage done by shockwave for BIG|HUGE
|
||||
maybe_shockwave_damage_adjust(ship_objp, other_obj, &damage);
|
||||
@@ -2697,10 +2810,19 @@ static void ship_do_damage(object *ship_objp, object *other_obj, const vec3d *hi
|
||||
// diag_printf2("Simulated Hull for Ship %s hit, dropping from %.32f to %d.\n", shipp->ship_name, (int) ( ship_objp->sim_hull_strength * 100 ), (int) ( ( ship_objp->sim_hull_strength - damage ) * 100 ) );
|
||||
ship_objp->sim_hull_strength -= damage;
|
||||
ship_objp->sim_hull_strength = MAX(0.0f, ship_objp->sim_hull_strength);
|
||||
if (damage_hook_active) {
|
||||
ship_run_damage_hook(ship_objp, other_obj, weapon_info_index, damage_type_idx, quadrant, source, wash_damage, damage_before);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
ship_objp->hull_strength -= damage;
|
||||
|
||||
// a lethal hit runs the hook now, before the ship's death processing below
|
||||
if (damage_hook_active && ship_objp->hull_strength <= 0.0f) {
|
||||
ship_run_damage_hook(ship_objp, other_obj, weapon_info_index, damage_type_idx, quadrant, source, wash_damage, damage_before);
|
||||
damage_hook_ran = true;
|
||||
}
|
||||
}
|
||||
|
||||
// let damage gauge know that player ship just took damage
|
||||
@@ -2800,6 +2922,10 @@ static void ship_do_damage(object *ship_objp, object *other_obj, const vec3d *hi
|
||||
}
|
||||
}
|
||||
|
||||
if (damage_hook_active && !damage_hook_ran) {
|
||||
ship_run_damage_hook(ship_objp, other_obj, weapon_info_index, damage_type_idx, quadrant, source, wash_damage, damage_before);
|
||||
}
|
||||
|
||||
if (!global_damage) {
|
||||
maybe_play_conditional_impacts(impact_data, other_obj, ship_objp, true, submodel_num, hitpos, local_hitpos, hit_normal);
|
||||
}
|
||||
@@ -3006,7 +3132,7 @@ void ship_apply_tag(ship *shipp, int tag_level, float tag_time, object *target,
|
||||
// hitpos is in world coordinates.
|
||||
// if quadrant is not -1, then that part of the shield takes damage properly.
|
||||
// (it might be possible to make `other_obj` const, but that would set off another const-cascade)
|
||||
void ship_apply_local_damage(object *ship_objp, object *other_obj, const vec3d *hitpos, float damage, int damage_type_idx, int quadrant, bool create_spark, int submodel_num, const vec3d *hit_normal, float hit_dot, const vec3d* local_hitpos)
|
||||
void ship_apply_local_damage(object *ship_objp, object *other_obj, const vec3d *hitpos, float damage, int damage_type_idx, int quadrant, bool create_spark, int submodel_num, const vec3d *hit_normal, float hit_dot, const vec3d* local_hitpos, DamageSource source)
|
||||
{
|
||||
Assert(ship_objp); // Goober5000
|
||||
Assert(other_obj); // Goober5000
|
||||
@@ -3103,7 +3229,7 @@ void ship_apply_local_damage(object *ship_objp, object *other_obj, const vec3d *
|
||||
ship_do_healing(ship_objp, other_obj, hitpos, damage, quadrant, submodel_num, -1, hit_normal, local_hitpos);
|
||||
create_sparks = false;
|
||||
} else {
|
||||
ship_do_damage(ship_objp, other_obj, hitpos, damage, quadrant, submodel_num, damage_type_idx, false, hit_dot, hit_normal, local_hitpos);
|
||||
ship_do_damage(ship_objp, other_obj, hitpos, damage, quadrant, submodel_num, damage_type_idx, false, hit_dot, hit_normal, local_hitpos, source);
|
||||
}
|
||||
|
||||
// DA 5/5/98: move ship_hit_create_sparks() after do_damage() since number of sparks depends on hull strength
|
||||
@@ -3150,7 +3276,7 @@ void ship_apply_local_damage(object *ship_objp, object *other_obj, const vec3d *
|
||||
// You can pass force_center==NULL if you the damage doesn't come from anywhere,
|
||||
// like for debug keys to damage an object or something. It will
|
||||
// assume damage is non-directional and will apply it correctly.
|
||||
void ship_apply_global_damage(object *ship_objp, object *other_obj, const vec3d *force_center, float damage, int damage_type_idx)
|
||||
void ship_apply_global_damage(object *ship_objp, object *other_obj, const vec3d *force_center, float damage, int damage_type_idx, DamageSource source)
|
||||
{
|
||||
Assert(ship_objp); // Goober5000 (but not other_obj in case of sexp)
|
||||
|
||||
@@ -3187,7 +3313,7 @@ void ship_apply_global_damage(object *ship_objp, object *other_obj, const vec3d
|
||||
ship_do_healing(ship_objp, other_obj, &world_hitpos, damage, -1, damage_type_idx);
|
||||
else
|
||||
// Do damage on local point
|
||||
ship_do_damage(ship_objp, other_obj, &world_hitpos, damage, shield_quad, -1 , damage_type_idx);
|
||||
ship_do_damage(ship_objp, other_obj, &world_hitpos, damage, shield_quad, -1 , damage_type_idx, false, 1.f, nullptr, nullptr, source);
|
||||
} else {
|
||||
// Since an force_center wasn't specified, this is probably just a debug key
|
||||
// to kill an object. So pick a shield quadrant and a point on the
|
||||
@@ -3196,7 +3322,7 @@ void ship_apply_global_damage(object *ship_objp, object *other_obj, const vec3d
|
||||
|
||||
int n_quadrants = static_cast<int>(ship_objp->shield_quadrant.size());
|
||||
for (int i=0; i<n_quadrants; i++){
|
||||
ship_do_damage(ship_objp, other_obj, &world_hitpos, damage/n_quadrants, i, -1, damage_type_idx);
|
||||
ship_do_damage(ship_objp, other_obj, &world_hitpos, damage/n_quadrants, i, -1, damage_type_idx, false, 1.f, nullptr, nullptr, source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-2
@@ -54,12 +54,20 @@ std::pair<std::optional<ConditionData>, float> do_subobj_hit_stuff(object *ship_
|
||||
// (it might be possible to make `target` const, but that would set off another const-cascade)
|
||||
extern void ship_apply_tag(ship *ship_p, int tag_level, float tag_time, object *target, const vec3d *start, int ssm_index, int ssm_team);
|
||||
|
||||
// Where a ship damage application came from, for the On Ship Damage hook. Inferred uses the damaging object type and
|
||||
// the engine wash flag. Collision and Explosion are for callers whose damaging object cannot tell them apart.
|
||||
enum class DamageSource {
|
||||
Inferred,
|
||||
Collision,
|
||||
Explosion,
|
||||
};
|
||||
|
||||
// This gets called to apply damage when something hits a particular point on a ship.
|
||||
// This assumes that whoever called this knows if the shield got hit or not.
|
||||
// hitpos is in world coordinates.
|
||||
// if quadrant is not -1, then that part of the shield takes damage properly.
|
||||
// (it might be possible to make `other_obj` const, but that would set off another const-cascade)
|
||||
void ship_apply_local_damage(object *ship_obj, object *other_obj, const vec3d *hitpos, float damage, int damage_type_idx, int quadrant, bool create_spark=true, int submodel_num=-1, const vec3d *hit_normal=nullptr, float hit_dot = 1.f, const vec3d* local_hitpos = nullptr);
|
||||
void ship_apply_local_damage(object *ship_obj, object *other_obj, const vec3d *hitpos, float damage, int damage_type_idx, int quadrant, bool create_spark=true, int submodel_num=-1, const vec3d *hit_normal=nullptr, float hit_dot = 1.f, const vec3d* local_hitpos = nullptr, DamageSource source = DamageSource::Inferred);
|
||||
|
||||
// This gets called to apply damage when a damaging force hits a ship, but at no
|
||||
// point in particular. Like from a shockwave. This routine will see if the
|
||||
@@ -67,7 +75,7 @@ void ship_apply_local_damage(object *ship_obj, object *other_obj, const vec3d *h
|
||||
// You can pass force_center==NULL if you the damage doesn't come from anywhere,
|
||||
// like for debug keys to damage an object or something. It will
|
||||
// assume damage is non-directional and will apply it correctly.
|
||||
void ship_apply_global_damage(object *ship_obj, object *other_obj, const vec3d *force_center, float damage, int damage_type_idx);
|
||||
void ship_apply_global_damage(object *ship_obj, object *other_obj, const vec3d *force_center, float damage, int damage_type_idx, DamageSource source = DamageSource::Inferred);
|
||||
|
||||
// like above, but does not apply damage to shields
|
||||
void ship_apply_wash_damage(object *ship_obj, object *other_obj, float damage);
|
||||
|
||||
Reference in new issue
Block a user