use std::ptr::NonNull;
use shared::{F32Vector3, FromStatic, OwnedPtr};
use crate::{
DLList,
cs::{BlockId, MultiplayType, SummonParamType, WorldAreaTime},
};
use super::SosSignMan;
#[shared::singleton("CSEventMan")]
#[repr(C)]
pub struct CSEventManImp {
vftable: usize,
simple_info: usize,
dead_reset: usize,
obj_sfx: usize,
parts_damage: usize,
drop_item: usize,
sound: usize,
damage: usize,
dam_obj_hit: usize,
unk48: usize,
unk50: usize,
unk58: usize,
pub sos_sign: OwnedPtr<CSEventSosSignCtrl>,
unk68: usize,
obj_act_exec: usize,
unk78: usize,
bloodstain: usize,
pub script: OwnedPtr<CSEventScriptEventInfo>,
corpse: usize,
unk98: usize,
generator: usize,
unka8: usize,
system_flag: usize,
turn: usize,
pub world_area_time: OwnedPtr<CSEventWorldAreaTimeCtrl>,
fade_warp: usize,
unkd0: usize,
unkd8: usize,
retry_points: usize,
network_error_return_title_step: usize,
cutscene_warp: usize,
}
#[repr(C)]
pub struct CSEventScriptEventInfo {
vftable: usize,
pub event_info_by_block_id: DLList<OwnedPtr<EventInfoEntry>>,
}
#[repr(C)]
pub struct EventInfoEntry {
pub block_id: BlockId,
pub event_ids: DLList<u32>,
}
#[repr(C)]
pub struct CSEventSosSignData {
pub sign_position: F32Vector3,
pub sign_rotation: F32Vector3,
pub multiplay_type: MultiplayType,
unk19: u8,
pub is_sign_active: bool,
pub is_match_area_sign: bool,
pub is_near_far_sign: bool,
unk20: usize,
unk28: usize,
}
#[repr(C)]
pub struct CSEventSosSignCtrl {
vftable: usize,
unk8: [u8; 0x8],
pub data: CSEventSosSignData,
sign_sfx: usize,
pub sos_sign_man: Option<NonNull<SosSignMan>>,
pub summon_param_type: SummonParamType,
unk54: i32,
}
#[repr(C)]
pub struct CSEventWorldAreaTimeCtrl {
base: [u8; 0x40],
unk40: [u8; 0x68],
unka8: bool,
pub target_hours: u32,
pub target_minutes: u32,
pub target_seconds: u32,
pub fade_transition: bool,
pub black_screen_time: f32,
pub bonfire_entity_id: u32,
pub reset_world: bool,
pub reset_main_character: bool,
pub reset_magic_charges: bool,
pub restore_estus: bool,
pub show_clock: bool,
pub clock_startup_delay_s: f32,
pub clock_move_time_s: f32,
pub clock_finish_delay_s: f32,
pub fade_out_time: f32,
pub fade_in_time: f32,
pub fade_out_requested: bool,
pub update_elapsed_time: f32,
pub black_screen_elapsed_time: f32,
pub respawn_wait_flag: bool,
unked: bool,
unkee: bool,
unkef: bool,
unkf0: bool,
pub total_elapsed_time: f32,
pub black_screen_timeout: f32,
}
impl CSEventWorldAreaTimeCtrl {
pub fn fade_out_and_pass_time(&mut self, params: TimeTransitionParams) {
if self.fade_out_requested {
return;
}
self.fade_out_requested = true;
if let Ok(wat) = unsafe { WorldAreaTime::instance() } {
let current_total_seconds = (wat.clock.hours() as i64 * 3600)
+ (wat.clock.minutes() as i64 * 60)
+ wat.clock.seconds() as i64;
let delta_total_seconds = (params.add_hours as i64 * 3600)
+ (params.add_minutes as i64 * 60)
+ params.add_seconds as i64;
let normalized_seconds =
((current_total_seconds + delta_total_seconds) % 86400 + 86400) % 86400;
self.target_hours = (normalized_seconds / 3600) as u32;
self.target_minutes = ((normalized_seconds % 3600) / 60) as u32;
self.target_seconds = (normalized_seconds % 60) as u32;
}
self.clock_startup_delay_s = params.clock_startup_delay_s;
self.clock_move_time_s = params.clock_move_time_s;
self.clock_finish_delay_s = params.clock_finish_delay_s;
self.black_screen_time = params.black_screen_time;
self.fade_transition = true;
self.show_clock = false;
self.bonfire_entity_id = params.bonfire_entity_id;
self.reset_world = params.reset_world;
self.reset_main_character = params.reset_main_character;
self.reset_magic_charges = params.reset_magic_charges;
self.restore_estus = params.restore_estus;
self.fade_out_time = params.fade_out_time;
self.fade_in_time = params.fade_in_time;
}
}
#[derive(Debug, Clone)]
pub struct TimeTransitionParams {
pub add_hours: i32,
pub add_minutes: i32,
pub add_seconds: i32,
pub black_screen_time: f32,
pub bonfire_entity_id: u32,
pub reset_world: bool,
pub reset_main_character: bool,
pub reset_magic_charges: bool,
pub restore_estus: bool,
pub clock_startup_delay_s: f32,
pub clock_move_time_s: f32,
pub clock_finish_delay_s: f32,
pub fade_out_time: f32,
pub fade_in_time: f32,
}
impl Default for TimeTransitionParams {
fn default() -> Self {
Self {
add_hours: 0,
add_minutes: 0,
add_seconds: 0,
black_screen_time: 1.5,
bonfire_entity_id: 0,
reset_world: false,
reset_main_character: false,
reset_magic_charges: false,
restore_estus: false,
clock_startup_delay_s: 0.0,
clock_move_time_s: 0.0,
clock_finish_delay_s: 0.0,
fade_out_time: 0.75,
fade_in_time: 0.5,
}
}
}
impl TimeTransitionParams {
pub fn bonfire_rest() -> Self {
Self {
reset_world: true,
reset_main_character: true,
reset_magic_charges: true,
restore_estus: true,
..Default::default()
}
}
pub fn time_skip(hours: i32, minutes: i32, seconds: i32) -> Self {
Self {
add_hours: hours,
add_minutes: minutes,
add_seconds: seconds,
..Default::default()
}
}
}