void detonate_if(const entity_id& id, const transformr& where, const logic_step& step) { step.get_cosmos()[id].dispatch_on_having_all<invariants::explosive>([&](const auto typed_handle) { detonate({ step, id, typed_handle.template get<invariants::explosive>(), where }); }); }
void demolitions_system::advance_cascade_explosions(const logic_step step) { auto& cosm = step.get_cosmos(); const auto& clk = cosm.get_clock(); cosm.for_each_having<components::cascade_explosion>( [&](const auto it) { const auto& cascade_def = it.template get<invariants::cascade_explosion>(); auto& cascade = it.template get<components::cascade_explosion>(); auto& when_next = cascade.when_next_explosion; if (clk.now >= when_next) { auto rng = cosm.get_nontemporal_rng_for(it); { const auto next_explosion_in_ms = rng.randval(cascade_def.explosion_interval_ms); when_next = clk.now; when_next.step += next_explosion_in_ms / clk.dt.in_milliseconds(); } { const auto angle_displacement = rng.randval_h(cascade_def.max_explosion_angle_displacement); const auto& body = it.template get<components::rigid_body>(); auto vel = body.get_velocity(); vel.rotate(angle_displacement, vec2()); body.set_velocity(vel); } auto expl_in = cascade_def.explosion; expl_in *= rng.randval_vm(1.f, cascade_def.explosion_scale_variation); expl_in.instantiate( step, it.get_logic_transform(), damage_cause(it) ); --cascade.explosions_left; if (0 == cascade.explosions_left) { step.queue_deletion_of(it, "Cascade explosions exhausted"); } } } ); }
void demolitions_system::detonate_fuses(const logic_step step) { auto& cosm = step.get_cosmos(); const auto& clk = cosm.get_clock(); cosm.for_each_having<components::hand_fuse>( [&](const auto& it) { const auto fuse_logic = fuse_logic_provider(it, step); fuse_logic.advance_arming_and_defusing(); auto& fuse = fuse_logic.fuse; const auto& fuse_def = fuse_logic.fuse_def; if (fuse.armed()) { { auto& when_beep = fuse.when_last_beep; if (!when_beep.was_set()) { when_beep = clk.now; /* Don't play the beep effect for the first time. */ } else { const auto beep = beep_math { fuse, fuse_def, clk }; if (beep.should_beep_again()) { fuse_def.beep_sound.start( step, sound_effect_start_input::fire_and_forget(fuse_logic.fused_transform), always_predictable_v ); when_beep = clk.now; } } } const auto when_armed = fuse.when_armed; const auto& fuse_def = it.template get<invariants::hand_fuse>(); if (clk.is_ready(fuse_def.fuse_delay_ms, when_armed)) { detonate_if(it, step); } } } ); }