From f13892a15549e727f39da4ef152fb74c7a1b20f2 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Sun, 24 Mar 2024 06:10:48 +0300 Subject: [PATCH] Added Chara Item Scaling for Auth 3D. --- src/DivaGL/auth_3d.cpp | 20 ++- src/DivaGL/rob/rob.cpp | 361 ++++++++++++++++++++++++++++++++++++++++- src/DivaGL/rob/rob.hpp | 1 + 3 files changed, 379 insertions(+), 3 deletions(-) diff --git a/src/DivaGL/auth_3d.cpp b/src/DivaGL/auth_3d.cpp index 5182768..4ceca43 100644 --- a/src/DivaGL/auth_3d.cpp +++ b/src/DivaGL/auth_3d.cpp @@ -449,6 +449,7 @@ struct auth_3d { object_info object_info; mat4* bone_mats; bool shadow; + bool chara_item; chara_index src_chara; chara_index dst_chara; int32_t pos; @@ -834,6 +835,14 @@ void auth_3d_id::set_chara_id(int32_t value) { } } +void auth_3d_id::set_chara_item(bool value) { + if (id >= 0 && ((id & 0x7FFF) < AUTH_3D_DATA_COUNT)) { + auth_3d* auth = &auth_3d_data->data[id & 0x7FFF]; + if (auth->id == id) + auth->chara_item = value; + } +} + void auth_3d_id::set_enable(bool value) { if (id >= 0 && ((id & 0x7FFF) < AUTH_3D_DATA_COUNT)) { auth_3d* auth = &auth_3d_data->data[id & 0x7FFF]; @@ -1092,7 +1101,10 @@ HOOK(void, FASTCALL, auth_3d_object_hrc_disp, 0x00000001401D04A0, auth_3d_object size_t rob_chara_smth = get_rob_chara_smth(); if (rob_chara_pv_data_array_check_chara_id(rob_chara_smth, auth->chara_id)) { size_t rob_chr = rob_chara_array_get(rob_chara_smth, auth->chara_id); - mat4_mul(rob_chara_get_adjust_data_mat(rob_chr), sub_140516740(rob_chr), &mat); + mat4_mul(auth->chara_item + ? rob_chara_get_item_adjust_data_mat(rob_chr) + : rob_chara_get_adjust_data_mat(rob_chr), + sub_140516740(rob_chr), &mat); if (auth->chara_id) disp_manager.set_shadow_type(SHADOW_STAGE); } @@ -1157,7 +1169,10 @@ HOOK(void, FASTCALL, auth_3d_object_disp, 0x00000001401D0970, auth_3d_object* o, if (rob_chara_pv_data_array_check_chara_id(rob_chara_smth, auth->chara_id)) { size_t rob_chr = rob_chara_array_get(rob_chara_smth, auth->chara_id); mat4 m; - mat4_mul(rob_chara_get_adjust_data_mat(rob_chr), sub_140516740(rob_chr), &m); + mat4_mul(auth->chara_item + ? rob_chara_get_item_adjust_data_mat(rob_chr) + : rob_chara_get_adjust_data_mat(rob_chr), + sub_140516740(rob_chr), &m); mat4_mul(&mat, &m, &mat); disp_manager.set_shadow_type(auth->chara_id ? SHADOW_STAGE : SHADOW_CHARA); } @@ -1313,6 +1328,7 @@ void auth_3d_patch() { WRITE_MEMORY_STRING(0x00000001401A72FF, "\x4C\x89\x40\x38", 0x04); WRITE_MEMORY_STRING(0x00000001401B316A, "\x48\x8B\x43\x68\x48\x89" "\x47\x68\x48\x8B\xC7\x48\x8B\x5C\x24\x48\x48\x83\xC4\x30\x5F\xC3", 0x16); + WRITE_MEMORY_STRING(0x00000001401D7A78, "\x44\x89\xBF\x98\x00\x00\x00", 0x07); INSTALL_HOOK(auth_3d_curve_array_free); INSTALL_HOOK(auth_3d_m_object_hrc_disp); diff --git a/src/DivaGL/rob/rob.cpp b/src/DivaGL/rob/rob.cpp index 2ff3dfd..21eaf5a 100644 --- a/src/DivaGL/rob/rob.cpp +++ b/src/DivaGL/rob/rob.cpp @@ -20,6 +20,22 @@ enum ExNodeType { EX_CLOTH = 0x04, }; +enum rob_chara_data_hand_adjust_type : uint16_t { + ROB_CHARA_DATA_HAND_ADJUST_NONE = (uint16_t)-1, + ROB_CHARA_DATA_HAND_ADJUST_NORMAL = 0x00, + ROB_CHARA_DATA_HAND_ADJUST_SHORT = 0x01, + ROB_CHARA_DATA_HAND_ADJUST_TALL = 0x02, + ROB_CHARA_DATA_HAND_ADJUST_MIN = 0x03, + ROB_CHARA_DATA_HAND_ADJUST_MAX = 0x04, + ROB_CHARA_DATA_HAND_ADJUST_OPPOSITE_CHARA = 0x05, + ROB_CHARA_DATA_HAND_ADJUST_CUSTOM = 0x06, + ROB_CHARA_DATA_HAND_ADJUST_1P = 0x07, + ROB_CHARA_DATA_HAND_ADJUST_2P = 0x08, + ROB_CHARA_DATA_HAND_ADJUST_3P = 0x09, + ROB_CHARA_DATA_HAND_ADJUST_4P = 0x0A, + ROB_CHARA_DATA_HAND_ADJUST_ITEM = 0x0F, // X +}; + struct rob_chara_age_age_object_vertex { vec3 position; vec3 normal; @@ -288,11 +304,47 @@ struct struc_389 { float_t last_set_frame; }; +static_assert(sizeof(struc_389) == 0x0C, "\"struc_389\" struct should have a size of 0x0C"); + +struct struc_406 { + float_t frame; + float_t field_4; + float_t step; +}; + +static_assert(sizeof(struc_406) == 0x0C, "\"struc_406\" struct should have a size of 0x0C"); + +struct rob_chara_data_hand_adjust { + bool enable; + int16_t scale_select; + rob_chara_data_hand_adjust_type type; + float_t current_scale; + float_t scale; + float_t duration; + float_t current_time; + float_t rotation_blend; + float_t scale_blend; + bool enable_scale; + bool disable_x; + bool disable_y; + bool disable_z; + vec3 offset; + vec3 field_30; + float_t arm_length; + int32_t field_40; +}; + +static_assert(sizeof(rob_chara_data_hand_adjust) == 0x44, "\"rob_chara_data_hand_adjust\" struct should have a size of 0x44"); + struct rob_chara_motion { uint32_t motion_id; uint32_t prev_motion_id; struc_389 frame_data; - uint8_t data[0x12E4]; + struc_406 step_data; + uint8_t data[0x1198]; + rob_chara_data_hand_adjust hand_adjust[2]; + rob_chara_data_hand_adjust hand_adjust_prev[2]; + uint8_t data1[0x30]; }; static_assert(sizeof(rob_chara_motion) == 0x12F8, "\"rob_chara_motion\" struct should have a size of 0x12F8"); @@ -596,6 +648,28 @@ struct rob_chara { static_assert(sizeof(rob_chara) == 0x8110, "\"rob_chara\" struct should have a size of 0x8110"); +struct rob_chara_item_adjust_x { + mat4 mat; + vec3 trans; + float_t scale; + + rob_chara_item_adjust_x(); + + void reset(); +}; + +struct rob_chara_arm_adjust_x { + float_t next_value; + float_t prev_value; + int32_t start_frame; + float_t duration; + float_t scale; + + rob_chara_arm_adjust_x(); + + void reset(); +}; + const mat4* (FASTCALL* rob_chara_bone_data_get_mats_mat)(size_t rob_bone_data, size_t index) = (const mat4 * (FASTCALL*)(size_t rob_bone_data, size_t index))0x0000000140419520; const char* (FASTCALL* chara_index_get_auth_3d_name)(chara_index chara_index) @@ -625,12 +699,128 @@ static bool& chara_refract = *(bool*)0x00000001411ADAFD; const mat4* rob_chara_item_equip_mat = 0; +rob_chara_item_adjust_x rob_chara_item_adjust_x_array[ROB_CHARA_COUNT]; +rob_chara_arm_adjust_x rob_chara_arm_adjust_x_array[ROB_CHARA_COUNT]; + static void rob_chara_age_age_array_disp(int32_t chara_id, bool reflect, bool chara_color); const mat4* rob_chara_get_adjust_data_mat(size_t rob_chr) { return &((rob_chara*)rob_chr)->data.adjust_data.mat; } +const mat4* rob_chara_get_item_adjust_data_mat(size_t rob_chr) { + int32_t chara_id = ((rob_chara*)rob_chr)->chara_id; + return &rob_chara_item_adjust_x_array[chara_id].mat; +} + +HOOK(void, FASTCALL, sub_1405044B0, 0x00000001405044B0, rob_chara* rob_chr) { + rob_chara_item_adjust_x& item_adjust = rob_chara_item_adjust_x_array[rob_chr->chara_id]; + rob_chara_arm_adjust_x& arm_adjust = rob_chara_arm_adjust_x_array[rob_chr->chara_id]; + if (arm_adjust.duration > 0) { + float_t blend = 1.0f; + if (fabsf(arm_adjust.duration) > 0.000001f) + blend = (rob_chr->data.motion.frame_data.frame + - (float_t)arm_adjust.start_frame) / arm_adjust.duration; + + blend = clamp_def(blend, 0.0f, 1.0f); + if (fabsf(blend - 1.0f) <= 0.000001f) + arm_adjust.duration = -1.0f; + arm_adjust.scale = lerp_def(arm_adjust.prev_value, arm_adjust.next_value, blend); + + static float_t(FASTCALL * chara_size_table_get_value)(uint32_t id) + = (float_t(FASTCALL*)(uint32_t id))0x00000001405103C0; + + float_t default_scale = chara_size_table_get_value(1); + item_adjust.scale = default_scale + (rob_chr->data.adjust_data.scale + - default_scale) * arm_adjust.scale; + } + + originalsub_1405044B0(rob_chr); +} + +static void rob_chara_data_adjuct_set_trans(rob_chara_adjust_data* rob_chr_adj, + rob_chara_item_adjust_x* rob_chr_itm_adj_x, vec3& trans, bool pos_adjust, vec3* global_trans) { + float_t scale = rob_chr_adj->scale; + float_t item_scale = rob_chr_itm_adj_x->scale; + vec3 _offset = rob_chr_adj->offset; + if (global_trans) + _offset.y += global_trans->y; + + vec3 _trans = trans; + vec3 _item_trans = trans; + if (rob_chr_adj->height_adjust) { + _trans.y += rob_chr_adj->pos_adjust_y; + _item_trans.y += rob_chr_adj->pos_adjust_y; + } + else { + vec3 temp = (_trans - _offset) * scale + _offset; + vec3 arm_temp = (_item_trans - _offset) * item_scale + _offset; + + if (!rob_chr_adj->offset_x) { + _trans.x = temp.x; + _item_trans.x = arm_temp.x; + } + + if (!rob_chr_adj->offset_y) { + _trans.y = temp.y; + _item_trans.y = arm_temp.y; + } + + if (!rob_chr_adj->offset_z) { + _trans.z = temp.z; + _item_trans.z = arm_temp.z; + } + } + + if (pos_adjust) { + _trans = rob_chr_adj->pos_adjust + _trans; + _item_trans = rob_chr_adj->pos_adjust + _item_trans; + } + + rob_chr_adj->trans = _trans - trans * scale; + rob_chr_itm_adj_x->trans = _item_trans - trans * item_scale; +} + +HOOK(void, FASTCALL, rob_chara_set_data_adjust_mat, 0x00000001405050D0, + rob_chara* rob_chr, rob_chara_adjust_data* rob_chr_adj, bool pos_adjust) { + mat4 mat = *rob_chara_bone_data_get_mats_mat((size_t)rob_chr->bone_data, ROB_BONE_N_HARA_CP); + + vec3 trans; + mat4_transpose(&mat, &mat); + mat4_get_translation(&mat, &trans); + + rob_chara_item_adjust_x* item_adjust = &rob_chara_item_adjust_x_array[rob_chr->chara_id]; + + vec3* global_trans = 0; + if (rob_chr_adj->get_global_trans) { + static vec3* (FASTCALL * rob_chara_bone_data_get_global_trans)(size_t rob_bone_data) + = (vec3 * (FASTCALL*)(size_t rob_bone_data))0x0000000140419360; + + global_trans = rob_chara_bone_data_get_global_trans((size_t)rob_chr->bone_data); + } + rob_chara_data_adjuct_set_trans(rob_chr_adj, item_adjust, trans, pos_adjust, global_trans); + + float_t scale = rob_chr_adj->scale; + mat4_scale(scale, scale, scale, &rob_chr_adj->mat); + mat4_set_translation(&rob_chr_adj->mat, &rob_chr_adj->trans); + mat4_transpose(&rob_chr_adj->mat, &rob_chr_adj->mat); + + float_t item_scale = item_adjust->scale; + mat4_scale(item_scale, item_scale, item_scale, &item_adjust->mat); + mat4_set_translation(&item_adjust->mat, &item_adjust->trans); + mat4_transpose(&item_adjust->mat, &item_adjust->mat); +} + +HOOK(void, FASTCALL, rob_chara_reset_data, 0x0000000140507210, rob_chara* rob_chr, rob_chara_pv_data* pv_data) { + rob_chara_item_adjust_x& item_adjust = rob_chara_item_adjust_x_array[rob_chr->chara_id]; + rob_chara_arm_adjust_x& arm_adjust = rob_chara_arm_adjust_x_array[rob_chr->chara_id]; + + item_adjust.reset(); + arm_adjust.reset(); + originalrob_chara_reset_data(rob_chr, pv_data); + item_adjust.scale = rob_chr->data.adjust_data.scale; +} + static void sub_140512C20(rob_chara_item_equip* rob_itm_equip) { if (rob_itm_equip->field_D0.is_null() || rob_itm_equip->field_D4 == -1) return; @@ -747,8 +937,154 @@ HOOK(void, FASTCALL, rob_chara_item_equip_disp, 0x0000000140512950, disp_manager.set_shadow_type(); } +HOOK(void, FASTCALL, rob_chara_set_chara_size, 0x0000000140516810, rob_chara* rob_chr, float_t value) { + originalrob_chara_set_chara_size(rob_chr, value); + rob_chara_item_adjust_x& item_adjust = rob_chara_item_adjust_x_array[rob_chr->chara_id]; + item_adjust.scale = value; +} + +HOOK(void, FASTCALL, sub_1405335C0, 0x0000001405335C0, struc_223* a1) { + originalsub_1405335C0(a1); + int32_t chara_id = ((rob_chara*)((size_t)a1 - 0x19C8))->chara_id; + rob_chara_arm_adjust_x_array[chara_id].reset(); +} + +HOOK(void, FASTCALL, mothead_func_32, 0x0000000140533C00, struct mothead_func_data* func_data, + void* data, const struct mothead_data* mhd_data, int64_t frame) { + float_t v8 = (float_t)((int16_t*)data)[0]; + int32_t v5 = ((int32_t*)data)[1]; + float_t v9 = ((float_t*)data)[2]; + int32_t v10 = ((int32_t*)data)[3]; + + if (v8 != (int16_t)0xFA0C || v10 != 0xD62721C5) { // X + originalmothead_func_32(func_data, data, mhd_data, frame); + return; + } + + size_t rob_chr_data = *(size_t*)((size_t)func_data + 0x08); + rob_chara* rob_chr = ((rob_chara*)((size_t)rob_chr_data - 0x440)); + + float_t value = v9; + float_t duration = (float_t)v5; + rob_chara_arm_adjust_x& arm_adjust = rob_chara_arm_adjust_x_array[rob_chr->chara_id]; + arm_adjust.next_value = value; + arm_adjust.prev_value = arm_adjust.scale; + arm_adjust.start_frame = (int32_t)frame; + arm_adjust.duration = max_def(duration, 0.0f); + return; +} + +HOOK(bool, FASTCALL, sub_14053ACA0, 0x000000014053ACA0, rob_chara* rob_chr, int32_t hand) { + if (hand >= 2 || !rob_chr->data.motion.hand_adjust[hand].enable) + return false; + + rob_chara_item_adjust_x& item_adjust = rob_chara_item_adjust_x_array[rob_chr->chara_id]; + rob_chara_item_adjust_x item_adjust_temp = item_adjust; + float_t chara_scale = rob_chr->data.adjust_data.scale; + float_t adjust_scale = rob_chr->data.motion.hand_adjust[hand].current_scale; + item_adjust.scale = adjust_scale / chara_scale; + originalsub_14053ACA0(rob_chr, hand); + item_adjust = item_adjust_temp; + return true; +} + +HOOK(void, FASTCALL, rob_chara_set_hand_adjust, 0x000000014053C070, rob_chara* rob_chr, + rob_chara_data_hand_adjust* adjust, rob_chara_data_hand_adjust* prev_adjust) { + if (!adjust->enable) + return; + + static float_t(FASTCALL * chara_size_table_get_value)(uint32_t id) + = (float_t(FASTCALL*)(uint32_t id))0x00000001405103C0; + static float_t(FASTCALL * rob_chara_array_get_data_adjust_scale)(size_t rob_chr_smth, int32_t chara_id) + = (float_t(FASTCALL*)(size_t rob_chr_smth, int32_t chara_id))0x0000000140531F90; + + float_t chara_scale = rob_chr->data.adjust_data.scale; + float_t opposite_chara_scale = rob_chara_array_get_data_adjust_scale(get_rob_chara_smth(), rob_chr->chara_id ? 0 : 1); + bool chara_opposite_chara_same = fabsf(chara_scale - opposite_chara_scale) <= 0.000001f; + + switch (adjust->type) { + case ROB_CHARA_DATA_HAND_ADJUST_NORMAL: + adjust->scale = chara_size_table_get_value(1); + break; + case ROB_CHARA_DATA_HAND_ADJUST_SHORT: + adjust->scale = chara_size_table_get_value(2); + break; + case ROB_CHARA_DATA_HAND_ADJUST_TALL: + adjust->scale = chara_size_table_get_value(0); + break; + case ROB_CHARA_DATA_HAND_ADJUST_MIN: + adjust->scale = min_def(opposite_chara_scale, chara_scale); + break; + case ROB_CHARA_DATA_HAND_ADJUST_MAX: + adjust->scale = max_def(opposite_chara_scale, chara_scale); + break; + case ROB_CHARA_DATA_HAND_ADJUST_OPPOSITE_CHARA: + adjust->scale = opposite_chara_scale; + break; + case ROB_CHARA_DATA_HAND_ADJUST_1P: + adjust->scale = rob_chara_array_get_data_adjust_scale(get_rob_chara_smth(), 0); + break; + case ROB_CHARA_DATA_HAND_ADJUST_2P: + adjust->scale = rob_chara_array_get_data_adjust_scale(get_rob_chara_smth(), 1); + break; + case ROB_CHARA_DATA_HAND_ADJUST_3P: + adjust->scale = rob_chara_array_get_data_adjust_scale(get_rob_chara_smth(), 2); + break; + case ROB_CHARA_DATA_HAND_ADJUST_4P: + adjust->scale = rob_chara_array_get_data_adjust_scale(get_rob_chara_smth(), 3); + break; + case ROB_CHARA_DATA_HAND_ADJUST_ITEM: // X + adjust->scale = rob_chara_item_adjust_x_array[rob_chr->chara_id].scale; + break; + } + + if (adjust->scale_select == 1 && adjust->enable_scale && chara_opposite_chara_same) { + adjust->scale_select = 0; + adjust->rotation_blend = prev_adjust->rotation_blend; + adjust->disable_x = prev_adjust->disable_x; + adjust->disable_y = prev_adjust->disable_y; + adjust->disable_z = prev_adjust->disable_z; + adjust->scale_blend = 1.0f; + } + + float_t prev_scale; + if (prev_adjust->enable || prev_adjust->scale_select == 1) + prev_scale = prev_adjust->current_scale; + else + prev_scale = chara_scale; + + float_t scale; + if (adjust->scale_select == 1) + scale = adjust->scale; + else + scale = chara_scale; + + if (fabsf(prev_scale - scale * adjust->scale_blend) <= 0.000001f || adjust->duration <= adjust->current_time + || fabsf(adjust->duration - adjust->current_time) <= 0.000001f) { + adjust->current_scale = lerp_def(prev_scale, scale, adjust->scale_blend); + if (fabsf(adjust->current_scale - chara_scale) <= 0.000001f + && adjust->type != ROB_CHARA_DATA_HAND_ADJUST_ITEM) { + adjust->current_scale = chara_scale; + adjust->enable = false; + } + } + else { + float_t t = (adjust->current_time + 1.0f) / (adjust->duration + 1.0f); + adjust->current_scale = lerp_def(prev_scale, scale, t * adjust->scale_blend); + adjust->current_time += rob_chr->data.motion.step_data.frame; + } +} + void rob_patch() { + INSTALL_HOOK(rob_chara_set_data_adjust_mat); + INSTALL_HOOK(rob_chara_reset_data); + INSTALL_HOOK(sub_1405044B0); INSTALL_HOOK(rob_chara_item_equip_disp); + INSTALL_HOOK(rob_chara_set_chara_size); + INSTALL_HOOK(sub_1405335C0); + INSTALL_HOOK(mothead_func_32); + INSTALL_HOOK(sub_14053ACA0); + INSTALL_HOOK(rob_chara_set_hand_adjust); } void rob_chara_age_age_object::disp(size_t chara_index, @@ -857,6 +1193,29 @@ bone_node* rob_chara_item_equip_object::get_bone_node(const char* name) { return get_bone_node(get_bone_index(name)); } +rob_chara_item_adjust_x::rob_chara_item_adjust_x() : scale() { + reset(); +} + +void rob_chara_item_adjust_x::reset() { + mat4_translate(&trans, &mat); + mat4_transpose(&mat, &mat); + scale = 1.0f; +} + +rob_chara_arm_adjust_x::rob_chara_arm_adjust_x() : next_value(), +prev_value(), start_frame(), duration(), scale() { + reset(); +} + +void rob_chara_arm_adjust_x::reset() { + next_value = 0.0f; + prev_value = 0.0f; + start_frame = -1; + duration = -1.0f; + scale = 1.0f; +} + static void rob_chara_age_age_disp(rob_chara_age_age* arr, int32_t chara_id, bool reflect, bool chara_color) { bool npr = !!render_manager->npr_param; diff --git a/src/DivaGL/rob/rob.hpp b/src/DivaGL/rob/rob.hpp index 4077a6f..06b78a1 100644 --- a/src/DivaGL/rob/rob.hpp +++ b/src/DivaGL/rob/rob.hpp @@ -707,5 +707,6 @@ extern bool (FASTCALL* rob_chara_pv_data_array_check_chara_id)(size_t rob_chr_sm extern const mat4* rob_chara_item_equip_mat; extern const mat4* rob_chara_get_adjust_data_mat(size_t rob_chr); +extern const mat4* rob_chara_get_item_adjust_data_mat(size_t rob_chr); extern void rob_patch();