Files
botw/src/KingSystem/Mii/miiUMii.cpp
T

327 lines
12 KiB
C++

#include "KingSystem/Mii/miiUMii.h"
#include <container/seadSafeArray.h>
#include <random/seadGlobalRandom.h>
#include "KingSystem/ActorSystem/actActorParamMgr.h"
#include "KingSystem/Mii/miiModelCreator.h"
#include "KingSystem/Resource/Actor/resResourceUMii.h"
#include "KingSystem/Utils/InitTimeInfo.h"
namespace ksys::mii {
struct Constants {
util::InitConstants init_constants;
sead::Vector3f eye_ctrl_base_offset{0.0, 0.03, 0.0};
sead::SafeArray<sead::SafeString, 4> rot_names{{
"rot_cravicle",
"rot_arm",
"rot_leg",
"rot_crotch",
}};
};
static Constants s_constants;
constexpr sead::SafeArray<float, 4> s_eye_highlight_values{{1.0, 0.5, 0.2, 0.0}};
UMii::UMii() : agl::utl::IParameterIO("umii", 0) {
mUser = "Dummy";
addObj(&ffsd, "ffsd");
ffsd.no_use_ffsd.init(false, "no_use_ffsd", "Miiデータを使用しない(NPCプロフィールとして扱う)",
&ffsd);
ffsd.type.init(0, "type", "参照先", &ffsd);
addObj(&body, "body");
body.race.init(0, "race", "種族", &body);
body.type.init(0, "type", "種類", &body);
body.number.init(0, "number", "番号", &body);
body.weight.init(1, "weight", "体重", &body);
body.height.init(0, "height", "身長", &body);
addObj(&personal, "personal");
personal.sex_age.init(1, "sex_age", "性別世代", &personal);
personal.fav_color.init(0, "fav_color", "お気に入りカラー", &personal);
personal.sub_color_1.init(-1, "sub_color_1", "サブカラー1", &personal);
personal.sub_color_2.init(-1, "sub_color_2", "サブカラー2", &personal);
personal.head_fav_color.init(-1, "head_fav_color", "お気に入りカラー(帽子)", &personal);
personal.shoulder_fav_color.init(-1, "shoulder_fav_color", "お気に入りカラー(リュック)",
&personal);
personal.shoulder_sub_color_1.init(-1, "shoulder_sub_color_1", "サブカラー1(リュック)",
&personal);
personal.personality.init(sead::SafeString::cEmptyString, "personality", "性格", &personal);
personal.voice_type.init("Normal1", "voice_type", "ボイスタイプ", &personal);
addObj(&common, "common");
common.backpack.init(-1, "backpack", "背負いもの", &common);
common.hat.init(-1, "hat", "帽子", &common);
common.no_hat_always.init(false, "no_hat_always", "常時帽子Off", &common);
common.body_correct.init(false, "body_correct", "体形補正", &common);
common.is_mid_age.init(false, "is_mid_age", "中年扱い(ゲルド用)", &common);
common.rot_cravicle.init(0.0, s_constants.rot_names[0], s_rot_labels[0], &common);
common.rot_arm.init(0.0, s_constants.rot_names[1], s_rot_labels[1], &common);
common.rot_leg.init(0.0, s_constants.rot_names[2], s_rot_labels[2], &common);
common.rot_crotch.init(0.0, s_constants.rot_names[3], s_rot_labels[3], &common);
addObj(&face.shape, "shape");
face.shape.jaw.init(0, "jaw", "顎形状", &face.shape);
face.shape.wrinkle.init(0, "wrinkle", "しわ", &face.shape);
face.shape.make.init(0, "make", "化粧", &face.shape);
face.shape.trans_v.init(0, "trans_v", "縦移動", &face.shape);
face.shape.scale.init(1.0, "scale", "拡縮", &face.shape);
face.shape.skin_color.init(0, "skin_color", "肌の色", &face.shape);
addObj(&face.hair, "hair");
face.hair.type.init(Hair::Type_Invalid, "type", "髪型", &face.hair);
face.hair.color.init(1, "color", "髪の色", &face.hair);
face.hair.flip.init(false, "flip", "反転", &face.hair);
addObj(&face.eye, "eye");
face.eye.type.init(2, "type", "種類", &face.eye);
face.eye.color.init(0, "color", "瞳の色", &face.eye);
face.eye.trans_v.init(12.0, "trans_v", "縦移動", &face.eye);
face.eye.trans_u.init(2.0, "trans_u", "横移動", &face.eye);
face.eye.rotate.init(0.0, "rotate", "回転", &face.eye);
face.eye.scale.init(4.0, "scale", "拡縮", &face.eye);
face.eye.aspect.init(3.0, "aspect", "縦拡縮", &face.eye);
face.eye.eyeball_trans_u.init(0.0, "eyeball_trans_u", "瞳上下オフセット", &face.eye);
face.eye.eyeball_trans_v.init(0.0, "eyeball_trans_v", "瞳左右オフセット", &face.eye);
face.eye.eyeball_scale.init(0.0, "eyeball_scale", "瞳拡縮オフセット", &face.eye);
face.eye.highlight_bright.init(0, "highlight_bright", "ハイライトの明るさ", &face.eye);
face.eye.highlight_value = s_eye_highlight_values[0];
addObj(&face.eye_ctrl, "eye_ctrl");
face.eye_ctrl.base_offset.init(s_constants.eye_ctrl_base_offset, "base_offset",
"基準位置オフセット", &face.eye_ctrl);
face.eye_ctrl.translim_out.init(0.2, "translim_out", "外移動量上限", &face.eye_ctrl);
face.eye_ctrl.translim_in.init(0.12, "translim_in", "内移動量上限", &face.eye_ctrl);
face.eye_ctrl.translim_d.init(0.3, "translim_d", "下移動量上限", &face.eye_ctrl);
face.eye_ctrl.translim_u.init(0.1, "translim_u", "上移動量上限", &face.eye_ctrl);
face.eye_ctrl.neck_offset_ud.init(0.0, "neck_offset_ud", "首向け上下角オフセット",
&face.eye_ctrl);
addObj(&face.eyebrow, "eyebrow");
face.eyebrow.type.init(0, "type", "種類", &face.eyebrow);
face.eyebrow.color.init(1, "color", "", &face.eyebrow);
face.eyebrow.trans_v.init(7.0, "trans_v", "縦移動", &face.eyebrow);
face.eyebrow.trans_u.init(2.0, "trans_u", "横移動", &face.eyebrow);
face.eyebrow.rotate.init(0.0, "rotate", "回転", &face.eyebrow);
face.eyebrow.scale.init(4.0, "scale", "拡縮", &face.eyebrow);
face.eyebrow.aspect.init(3.0, "aspect", "縦拡縮", &face.eyebrow);
addObj(&face.nose, "nose");
face.nose.type.init(1, "type", "種類", &face.nose);
face.nose.trans_v.init(9.0, "trans_v", "縦移動", &face.nose);
face.nose.scale.init(4.0, "scale", "拡縮", &face.nose);
addObj(&face.mouth, "mouth");
face.mouth.type.init(3, "type", "種類", &face.mouth);
face.mouth.color.init(0, "color", "口紅の色", &face.mouth);
face.mouth.trans_v.init(13.0, "trans_v", "縦移動", &face.mouth);
face.mouth.scale.init(4.0, "scale", "拡縮", &face.mouth);
face.mouth.aspect.init(3.0, "aspect", "縦拡縮", &face.mouth);
addObj(&face.beard, "beard");
face.beard.mustache.init(0, "mustache", "口髭の種類", &face.beard);
face.beard.scale.init(0.0, "scale", "口髭拡縮", &face.beard);
face.beard.type.init(0, "type", "アゴ髭の種類", &face.beard);
face.beard.color.init(0, "color", "髭の色", &face.beard);
addObj(&face.glass, "glass");
face.glass.type.init(0, "type", "種類", &face.glass);
face.glass.color.init(0, "color", "", &face.glass);
addObj(&korok, "korog"); // sic
korok.mask.init(0, "mask", "お面", &korok);
korok.skin_color.init(0, "skin_color", "肌の色", &korok);
korok.left_plant.init(0, "left_plant", "手持ち枝(左)", &korok);
korok.right_plant.init(0, "right_plant", "手持ち枝(右)", &korok);
addObj(&goron, "goron");
goron.skin_color.init(0, "skin_color", "肌の色", &goron);
addObj(&gerudo, "gerudo");
gerudo.hair.init(0, "hair", "", &gerudo);
gerudo.hair_color.init(0, "hair_color", "髪の色", &gerudo);
gerudo.glass.init(0, "glass", "眼鏡", &gerudo);
gerudo.glass_color.init(0, "glass_color", "眼鏡の色", &gerudo);
gerudo.skin_color.init(0, "skin_color", "肌の色", &gerudo);
gerudo.lip_color.init(0, "lip_color", "唇の色", &gerudo);
addObj(&rito, "rito");
rito.body_color.init(0, "body_color", "身体の色", &rito);
rito.hair_color.init(-1, "hair_color", "髪の色", &rito);
addObj(&zora, "zora");
zora.body_color.init(0, "body_color", "身体の色", &zora);
}
UMii::~UMii() {
mActor = nullptr;
if (mActorParam) {
act::ActorParamMgr::instance()->unloadParam(mActorParam);
mActorParam = nullptr;
}
}
void UMii::load(agl::utl::ResParameterArchive archive, const sead::SafeString& user,
const u32& load_req_c) {
reset();
applyResParameterArchive(archive);
mUser = user;
doLoad(load_req_c);
face.eye.highlight_value = s_eye_highlight_values[face.eye.highlight_bright.ref()];
}
void UMii::reset() {
mUser = "Dummy";
ffsd.no_use_ffsd = false;
ffsd.type = 0;
body.race = 0;
body.type = 0;
body.number = 0;
body.weight = 1;
body.height = 0;
personal.sex_age = Personal::SexAge_Man;
personal.fav_color = 0;
personal.sub_color_1 = -1;
personal.sub_color_2 = -1;
personal.head_fav_color = -1;
personal.shoulder_fav_color = -1;
personal.shoulder_sub_color_1 = -1;
personal.personality = sead::SafeString::cEmptyString;
personal.voice_type = "Normal1";
common.backpack = -1;
common.hat = -1;
korok.mask = 0;
korok.skin_color = 0;
korok.left_plant = 0;
korok.right_plant = 0;
goron.skin_color = 0;
gerudo.hair = 0;
gerudo.hair_color = 0;
gerudo.glass = 0;
gerudo.glass_color = 0;
gerudo.skin_color = 0;
gerudo.lip_color = 0;
rito.body_color = 0;
rito.hair_color = -1;
zora.body_color = 0;
}
void UMii::doLoad(const u32& load_req_c) {
if (ffsd.type.ref() == FFSD::Type_1) {
mActorName = ModelCreator::instance()->getActorName({isFemale()});
void* x;
mActorParam = act::ActorParamMgr::instance()->loadParam(mActorName.cstr(), &mResHandle, &x,
load_req_c);
if (mActorParam) {
res::UMii* umii = nullptr;
if (!mActorParam->isA()) {
umii = act::ActorParam::sDummyResources.mUMii;
if (!umii)
umii = mActorParam->getRes().mUMii;
}
if (umii) {
applyResParameterArchive(umii->getArchive());
static const char* voice_types[2] = {
"Hylia_Man_Young_Normal04",
"Hylia_Woman_Young_Normal04",
};
personal.voice_type.ref() = voice_types[isFemale()];
} else {
act::ActorParamMgr::instance()->unloadParam(mActorParam);
mActorParam = nullptr;
mResHandle.requestUnload();
}
}
}
if (korok.mask.ref() == Korok::Mask_Random)
korok.mask = sead::GlobalRandom::instance()->getU32(Korok::Mask_Random);
if (korok.skin_color.ref() == Korok::SkinColor_Random)
korok.skin_color = sead::GlobalRandom::instance()->getU32(Korok::SkinColor_Random);
if (korok.left_plant.ref() == Korok::LeftPlant_Random)
korok.left_plant = sead::GlobalRandom::instance()->getU32(Korok::LeftPlant_Random);
if (korok.right_plant.ref() == Korok::RightPlant_Random)
korok.right_plant = sead::GlobalRandom::instance()->getU32(Korok::RightPlant_Random);
}
bool UMii::isFemale() const {
return personal.sex_age.ref() > Personal::SexAge_OldMan;
}
int UMii::getHeightWeightIndex() const {
return 3 * *body.height + *body.weight;
}
UMii::Personal::Age UMii::getAge() const {
if (getSexAge() == Personal::SexAge_Boy || getSexAge() == Personal::SexAge_Girl)
return Personal::Age_Child;
if (getSexAge() == Personal::SexAge_Man || getSexAge() == Personal::SexAge_Woman)
return Personal::Age_Adult;
return Personal::Age_OldAdult;
}
void UMii::setKorokValues(const UMii::Korok& info) {
korok.mask = *info.mask;
korok.skin_color = *info.skin_color;
korok.left_plant = *info.left_plant;
korok.right_plant = *info.right_plant;
}
int UMii::sub_7100F4BE94() const {
const auto age = getAge();
if (age == Personal::Age_Child)
return 0;
if (age == Personal::Age_OldAdult)
return 3;
if (*body.race == Body::Race_Gerudo) {
if (*ffsd.no_use_ffsd) {
if (*common.is_mid_age)
return 1;
} else {
if (*body.number == 1)
return 1;
}
}
return isFemale() + 1;
}
int UMii::sub_7100F4BF0C() const {
switch (getSexAge()) {
case Personal::SexAge_Boy:
return 0;
case Personal::SexAge_Man:
return 1;
case Personal::SexAge_OldMan:
case Personal::SexAge_Woman:
return 2;
case Personal::SexAge_Girl:
return 0;
default:
return 2;
}
}
} // namespace ksys::mii