327 lines
11 KiB
C
327 lines
11 KiB
C
#include <ultra64.h>
|
|
#include "functions.h"
|
|
#include "variables.h"
|
|
|
|
extern void func_802EFA20(ParticleEmitter *, f32, f32);
|
|
extern void subaddie_set_state_with_direction(Actor *, s32, f32, s32);
|
|
extern void func_80328FB0(Actor *, f32);
|
|
extern void func_803300C0(ActorMarker *, void *);
|
|
|
|
|
|
typedef struct {
|
|
ActorMarker *unk0;
|
|
f32 unk4;
|
|
u8 pad8[0x1];
|
|
u8 unk9;
|
|
u8 unkA;
|
|
u8 unkB;
|
|
} ActorLocal_chSirSlush;
|
|
|
|
Actor *chSnowman_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx); //chSirSlush_draw
|
|
void chSnowman_update(Actor *this); //chSirSlush_update
|
|
|
|
/* .data */
|
|
ActorAnimationInfo chSnowmanAnimations[] = {
|
|
{0, 0.0f},
|
|
{ASSET_108_ANIM_SIR_SLUSH_IDLE, 0.8f},
|
|
{ASSET_109_ANIM_SIR_SLUSH_ATTACK, 4.0f},
|
|
{ASSET_220_ANIM_SIR_SLUSH_DIE, 1.6f}
|
|
};
|
|
|
|
enum chsnowman_state_e{
|
|
CHSNOWMAN_STATE_1_IDLE = 1,
|
|
CHSNOWMAN_STATE_2_ATTACK,
|
|
CHSNOWMAN_STATE_3_DIE
|
|
};
|
|
|
|
ActorInfo chSnowman = {
|
|
MARKER_B1_SIR_SLUSH, ACTOR_124_SIR_SLUSH, ASSET_377_MODEL_SIR_SLUSH,
|
|
CHSNOWMAN_STATE_1_IDLE, chSnowmanAnimations,
|
|
chSnowman_update, actor_update_func_80326224, chSnowman_draw,
|
|
0, 0x199, 0.0f, 0
|
|
};
|
|
|
|
/* .code */
|
|
Actor *chSnowman_draw(ActorMarker *marker, Gfx **gfx, Mtx **mtx, Vtx **vtx){
|
|
Actor *actor;
|
|
ActorLocal_chSirSlush *local;
|
|
|
|
actor = marker_getActor(marker);
|
|
local = (ActorLocal_chSirSlush *)&actor->local;
|
|
func_8033A45C(1, local->unk9);
|
|
func_8033A45C(2, local->unkA);
|
|
actor_draw(marker, gfx, mtx, vtx);
|
|
}
|
|
|
|
void __chSnowman_spawnSnowball(ActorMarker *marker){
|
|
Actor *actor;
|
|
Actor *other;
|
|
f32 player_position[3];
|
|
ActorMarker *m = *(ActorMarker **)▮
|
|
|
|
actor = marker_getActor(m);
|
|
other = spawn_child_actor(ACTOR_125_SNOWBALL, &actor);
|
|
if(m->unk14_21){
|
|
func_8034A174(m->unk44, 5, player_position);
|
|
}
|
|
else{
|
|
player_position[0] = actor->position[0];
|
|
player_position[1] = actor->position[1];
|
|
player_position[2] = actor->position[2];
|
|
player_position[1] += 150.0f;
|
|
}
|
|
other->position[0] = player_position[0];
|
|
other->position[1] = player_position[1];
|
|
other->position[2] = player_position[2];
|
|
}
|
|
|
|
void __chSnowman_spawnHat(ActorMarker *marker){
|
|
Actor *actor;
|
|
Actor *other;
|
|
f32 sp2C[3];
|
|
s32 sp28;
|
|
ActorMarker *m = *(ActorMarker **)▮
|
|
|
|
actor = marker_getActor(m);
|
|
other = spawn_child_actor(ACTOR_126_SIR_SLUSH_HAT, &actor);
|
|
|
|
func_8034A174(m->unk44, 6, sp2C);
|
|
|
|
other->position[0] = sp2C[0];
|
|
other->position[1] = sp2C[1];
|
|
other->position[2] = sp2C[2];
|
|
|
|
|
|
other->yaw = actor->yaw + 180.0f;
|
|
other->velocity[0] = other->velocity[1] = other->velocity[2] = 0.0f;
|
|
|
|
other->velocity[0] = 34.0f;
|
|
|
|
sp28 = (globalTimer_getTime() & 1)? 0x3C : 0x78;
|
|
ml_vec3f_yaw_rotate_copy(other->velocity, other->velocity, other->yaw - sp28);
|
|
other->velocity[1] = 30.0f;
|
|
}
|
|
|
|
void __chSnowman_spawnSnowballParticles(f32 position[3], s32 count){
|
|
static ParticleScaleAndLifetimeRanges D_80368694 = {
|
|
{0.4f, 1.55f},
|
|
{0.0f, 0.0f},
|
|
{0.0f, 0.01f},
|
|
{4.0f, 4.0f},
|
|
0.0f, 0.3f
|
|
};
|
|
static ParticleSettingsVelocityAccelerationPosition D_803686BC = {
|
|
{{-250.0f, 600.0f, -250.0f}, {350.0f, 960.0f, 350.0f}},
|
|
{{0.0f, -1200.0f, 0.0f}, {0.0f, -1200.0f, 0.0f}},
|
|
{{-80.0f, 0.0f, -80.0f}, {80.0f, 200.0f, 80.0f}}
|
|
};
|
|
|
|
ParticleEmitter *particleSpawner = partEmitMgr_newEmitter(count);
|
|
|
|
particleEmitter_setModel(particleSpawner, ASSET_378_MODEL_SNOWBALL);
|
|
particleEmitter_setPosition(particleSpawner, position);
|
|
particleEmitter_setVelocityAccelerationAndPositionRanges(particleSpawner, &D_803686BC);
|
|
particleEmitter_setAngularVelocityRange(particleSpawner, -600.0f, -600.0f, -600.0f, 600.0f, 600.0f, 600.0f);
|
|
particleEmitter_func_802EF9F8(particleSpawner, 0.01f);
|
|
particleEmitter_func_802EFA18(particleSpawner, 3);
|
|
func_802EFA20(particleSpawner, 1.0f, 1.3f);
|
|
particleEmitter_setSfx(particleSpawner, SFX_2F_ORANGE_SPLAT, 16000);
|
|
particleEmitter_setScaleAndLifetimeRanges(particleSpawner, &D_80368694);
|
|
particleEmitter_emitN(particleSpawner, count);
|
|
}
|
|
|
|
void __chSnowman_enterIdle(Actor *this){
|
|
ActorLocal_chSirSlush *local = (ActorLocal_chSirSlush *) &this->local;
|
|
subaddie_set_state_with_direction(this, CHSNOWMAN_STATE_1_IDLE, 0.01f, 1);
|
|
actor_loopAnimation(this);
|
|
local->unk4 = 0.4f;
|
|
}
|
|
|
|
void __chSnowman_enterDeath(Actor *this){
|
|
subaddie_set_state_with_direction(this, CHSNOWMAN_STATE_3_DIE, 0.01f, 1);
|
|
actor_playAnimationOnce(this);
|
|
}
|
|
|
|
void __chSnowman_setYawTarget(Actor *this, f32 max_rotation){
|
|
this->yaw_ideal = func_80329784(this);
|
|
func_80328FB0(this, 6.0f);
|
|
}
|
|
|
|
bool __chSnowman_isYawNearYawTarget(Actor *this, s32 max_angle_degree){
|
|
f32 dYaw;
|
|
dYaw = this->yaw - this->yaw_ideal;
|
|
if((dYaw < max_angle_degree) && (-max_angle_degree < dYaw)){
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int __chSnowman_isPlayerInAttackRange(Actor *this, s32 min_distance, s32 max_distance){
|
|
f32 player_position[3];
|
|
if(this->unkF4_8 == 0x33){
|
|
player_getPosition(player_position);
|
|
if( (this->position[1] + 500.0f < player_position[1]) || (player_position[1] < this->position[1] - 500.0f))
|
|
return 0;
|
|
}//L802E1F28
|
|
if(func_80329530(this, max_distance) && !func_80329530(this, min_distance)){
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int __chSnowman_func_802E1F70(ActorMarker *marker, s32 arg1){
|
|
if(marker->unk40_31 == 0xB){
|
|
marker->id = 0x287;
|
|
}
|
|
else{
|
|
marker->id = MARKER_B1_SIR_SLUSH;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void __chSnowman_deathCallback(ActorMarker *marker, ActorMarker *other_marker){
|
|
Actor *actor = marker_getActor(marker);
|
|
FUNC_8030E8B4(SFX_15_METALLIC_HIT_2, 1.0f, 30000, actor->position, 1500, 4500);
|
|
FUNC_8030E8B4(SFX_3EA_UNKNOWN, 1.0f, 30000, actor->position, 1500, 4500);
|
|
FUNC_8030E8B4(SFX_2F_ORANGE_SPLAT, 1.0f, 30000, actor->position, 1500, 4500);
|
|
|
|
__spawnQueue_add_1((GenFunction_1)__chSnowman_spawnHat, (s32)actor->marker);
|
|
if(map_get() == MAP_27_FP_FREEZEEZY_PEAK)
|
|
maSnowy_decRemaining();
|
|
__chSnowman_spawnSnowballParticles(actor->position, 0xC);
|
|
marker_despawn(actor->marker);
|
|
}
|
|
|
|
int __chSnowman_CCW_playerInProtectedZone(void){
|
|
static f32 ccw_no_attack_zone[3] = {350.0f, 600.0f, 65.0f};
|
|
f32 player_position[3];
|
|
if(map_get() == MAP_46_CCW_WINTER){
|
|
player_getPosition(player_position);
|
|
if(ml_vec3f_within_horizontal_distance(player_position, ccw_no_attack_zone, 900.0f))
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void chSnowman_update(Actor *this){
|
|
ActorLocal_chSirSlush *local = (ActorLocal_chSirSlush *) &this->local;
|
|
f32 dt;
|
|
|
|
|
|
dt = time_getDelta();
|
|
if(!this->volatile_initialized){
|
|
this->volatile_initialized = TRUE;
|
|
this->marker->propPtr->unk8_3 = 0;
|
|
actor_collisionOn(this);
|
|
marker_setCollisionScripts(this->marker, NULL, NULL, __chSnowman_deathCallback);
|
|
func_803300C0(this->marker, __chSnowman_func_802E1F70);
|
|
local->unk9 = 0;
|
|
local->unkA = 1;
|
|
local->unkB = 0;
|
|
local->unk4 = 0.0f;
|
|
anctrl_setTransitionDuration(this->anctrl, 0.8f);
|
|
anctrl_setAnimTimer(this->anctrl, randf());
|
|
func_8032BC18(this);
|
|
if(map_get() == MAP_27_FP_FREEZEEZY_PEAK){
|
|
local->unk0 = actorArray_findActorFromActorId(0x336)->marker;
|
|
maSnowy_incTotal();
|
|
}
|
|
}//L802E21D8
|
|
if(map_get() == MAP_27_FP_FREEZEEZY_PEAK){
|
|
if(maSlalom_isActive() || func_8038DD14()){
|
|
actor_collisionOff(this);
|
|
this->unk58_0 = 0;
|
|
return;
|
|
}
|
|
else{//L802E2224
|
|
actor_collisionOn(this);
|
|
this->unk58_0 = 1;
|
|
|
|
}
|
|
}//L802E223C
|
|
if(!subaddie_playerIsWithinSphere(this, 4000))
|
|
return;
|
|
|
|
if(!local->unkB && this->marker->unk14_21){
|
|
local->unkB = 1;
|
|
}//L802E2280
|
|
switch(this->state){
|
|
case CHSNOWMAN_STATE_1_IDLE://L802E22B0
|
|
local->unk9 = FALSE;
|
|
local->unkA = 1;
|
|
__chSnowman_setYawTarget(this, 6.0f);
|
|
if(!func_80329530(this, 3150)){
|
|
__chSnowman_enterDeath(this);
|
|
}
|
|
else if(
|
|
map_get() != MAP_27_FP_FREEZEEZY_PEAK
|
|
|| func_8038DD34(local->unk0) == 0
|
|
|| fileProgressFlag_get(FILEPROG_13_COMPLETED_TWINKLIES_MINIGAME)
|
|
){//L802E2318
|
|
if(0.0 < local->unk4){
|
|
if( (globalTimer_getTime() & 1)
|
|
|| player_movementGroup() == BSGROUP_A_FLYING
|
|
){//L802E236C
|
|
local->unk4 -= dt;
|
|
}
|
|
}
|
|
else{//L802E2380
|
|
if( __chSnowman_isPlayerInAttackRange(this, 500, 2750)
|
|
&& __chSnowman_isYawNearYawTarget(this, 3)
|
|
&& player_getWaterState() != BSWATERGROUP_2_UNDERWATER
|
|
&& !__chSnowman_CCW_playerInProtectedZone()
|
|
){
|
|
subaddie_set_state_with_direction(this, CHSNOWMAN_STATE_2_ATTACK, 0.01f, 1);
|
|
actor_playAnimationOnce(this);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case CHSNOWMAN_STATE_2_ATTACK://L802E23E8
|
|
if(!func_80329530(this, 3150)){
|
|
__chSnowman_enterDeath(this);
|
|
}//L802E240C
|
|
else if(
|
|
0.98 < anctrl_getAnimTimer(this->anctrl)
|
|
|| !__chSnowman_isPlayerInAttackRange(this, 500, 2750)
|
|
|| player_getWaterState() == BSWATERGROUP_2_UNDERWATER
|
|
|| __chSnowman_CCW_playerInProtectedZone()
|
|
){
|
|
__chSnowman_enterIdle(this);
|
|
}
|
|
else{
|
|
if(anctrl_getAnimTimer(this->anctrl) < 0.45){
|
|
__chSnowman_setYawTarget(this, 6.0f);
|
|
}
|
|
if( actor_animationIsAt(this, 0.19f)
|
|
|| actor_animationIsAt(this, 0.28f)
|
|
|| actor_animationIsAt(this, 0.37f)
|
|
){
|
|
FUNC_8030E8B4(SFX_A7_WOODEN_SWOSH, 1.3f, 18000, this->position, 800, 3050);
|
|
}//L802E24FC
|
|
if(actor_animationIsAt(this, 0.15f)){
|
|
func_8030E878(SFX_3F5_UNKNOWN, randf2(1.35f, 1.5f),32000, this->position, 800.0f, 3050.0f);
|
|
}//L802E2558
|
|
|
|
if(actor_animationIsAt(this, 0.45f)){
|
|
local->unk9 = TRUE;
|
|
}
|
|
else if(
|
|
actor_animationIsAt(this, 0.58f)
|
|
&& local->unkB
|
|
){
|
|
func_8030E878(SFX_8F_SNOWBALL_FLYING, randf2(0.95f, 1.05f), 30000, this->position, 800.0f, 3050.0f);
|
|
__spawnQueue_add_1((GenFunction_1)__chSnowman_spawnSnowball, (s32)this->marker);
|
|
local->unk9 = FALSE;
|
|
}
|
|
|
|
}
|
|
break;
|
|
case CHSNOWMAN_STATE_3_DIE://L802E2604
|
|
if(func_80329530(this, 3150)){
|
|
__chSnowman_enterIdle(this);
|
|
}
|
|
break;
|
|
}
|
|
}
|