papermario/src/battle/dmg_player.c

2537 lines
99 KiB
C

#include "common.h"
#include "effects.h"
#include "battle/battle.h"
#include "script_api/battle.h"
#include "sprite/player.h"
bool dispatch_damage_event_player(s32 damageAmount, s32 event, bool noHitSound);
bool dispatch_hazard_event_player(s32 damageAmount, s32 event);
API_CALLABLE(PlaySleepHitFX) {
fx_debuff(0, script->varTable[0], script->varTable[1], script->varTable[2]);
return ApiStatus_DONE2;
}
API_CALLABLE(PlayDizzyHitFX) {
fx_debuff(1, script->varTable[0], script->varTable[1], script->varTable[2]);
return ApiStatus_DONE2;
}
API_CALLABLE(PlayParalyzeHitFX) {
EffectInstance* debuffEffect = fx_debuff(2, script->varTable[0], script->varTable[1], script->varTable[2]);
debuffEffect->data.debuff->primCol.r = 200;
debuffEffect->data.debuff->primCol.g = 120;
debuffEffect->data.debuff->primCol.b = 0;
debuffEffect->data.debuff->envCol.r = 234;
debuffEffect->data.debuff->envCol.g = 193;
debuffEffect->data.debuff->envCol.b = 0;
return ApiStatus_DONE2;
}
API_CALLABLE(PlayPoisonHitFX) {
EffectInstance* debuffEffect = fx_debuff(2, script->varTable[0], script->varTable[1], script->varTable[2]);
debuffEffect->data.debuff->primCol.r = 60;
debuffEffect->data.debuff->primCol.g = 160;
debuffEffect->data.debuff->primCol.b = 0;
debuffEffect->data.debuff->envCol.r = 90;
debuffEffect->data.debuff->envCol.g = 240;
debuffEffect->data.debuff->envCol.b = 0;
return ApiStatus_DONE2;
}
API_CALLABLE(PlayStopHitFX) {
EffectInstance* debuffEffect = fx_debuff(2, script->varTable[0], script->varTable[1], script->varTable[2]);
debuffEffect->data.debuff->primCol.r = 205;
debuffEffect->data.debuff->primCol.g = 0;
debuffEffect->data.debuff->primCol.b = 40;
debuffEffect->data.debuff->envCol.r = 205;
debuffEffect->data.debuff->envCol.g = 32;
debuffEffect->data.debuff->envCol.b = 242;
return ApiStatus_DONE2;
}
API_CALLABLE(PlayFreezeHitSnowflakeFX) {
fx_big_snowflakes(0, script->varTable[0], script->varTable[1], script->varTable[2]);
return ApiStatus_DONE2;
}
API_CALLABLE(PlayFreezeHitParticleFX) {
Actor* actor = (Actor*)script->varTable[3];
f32 temp1 = actor->size.y;
f32 temp2 = actor->size.x / 2;
fx_misc_particles(0, script->varTable[0], script->varTable[1], script->varTable[2], temp1, temp2, 1.0f, 10, 30);
fx_misc_particles(1, script->varTable[0], script->varTable[1], script->varTable[2], temp1, temp2, 1.0f, 10, 30);
return ApiStatus_DONE2;
}
API_CALLABLE(PlayShrinkHitFX) {
s32 i;
for (i = 0; i < 20; i++) {
fx_floating_cloud_puff(0,
script->varTable[0] + rand_int(30) - 15,
script->varTable[1] + rand_int(20) - 15,
script->varTable[2] + 5,
1.0f,
25);
}
return ApiStatus_DONE2;
}
EvtScript EVS_PlaySleepHitFX = {
Call(PlaySleepHitFX)
Return
End
};
EvtScript EVS_PlayDizzyHitFX = {
Call(PlayDizzyHitFX)
Return
End
};
EvtScript EVS_PlayParalyzeHitFX = {
Call(PlayParalyzeHitFX)
Return
End
};
EvtScript EVS_PlayPoisonHitFX = {
Call(PlayPoisonHitFX)
Return
End
};
EvtScript EVS_PlayStopHitFX = {
Call(PlayStopHitFX)
Return
End
};
EvtScript EVS_PlayFreezeHitFX = {
Call(PlayFreezeHitSnowflakeFX)
Wait(8)
Call(PlayFreezeHitSnowflakeFX)
Wait(15)
Call(PlayFreezeHitParticleFX)
Return
End
};
EvtScript EVS_PlayShrinkHitFX = {
Call(PlayShrinkHitFX)
Return
End
};
void dispatch_event_player(s32 eventType) {
Actor* player = gBattleStatus.playerActor;
Evt* oldOnHitScript;
s32 oldOnHitID;
Evt* eventScript;
player->lastEventType = eventType;
oldOnHitScript = player->handleEventScript;
oldOnHitID = player->handleEventScriptID;
eventScript = start_script(&EVS_Player_HandleEvent, EVT_PRIORITY_A, EVT_FLAG_RUN_IMMEDIATELY);
player->handleEventScript = eventScript;
player->handleEventScriptID = eventScript->id;
eventScript->owner1.actor = NULL;
if (player->takeTurnScript != NULL) {
kill_script_by_ID(player->takeTurnScriptID);
player->takeTurnScript = NULL;
}
if (oldOnHitScript != NULL) {
kill_script_by_ID(oldOnHitID);
}
}
void dispatch_event_player_continue_turn(s32 eventType) {
Actor* player = gBattleStatus.playerActor;
Evt* oldOnHitScript;
s32 oldOnHitID;
Evt* eventScript;
player->lastEventType = eventType;
oldOnHitScript = player->handleEventScript;
oldOnHitID = player->handleEventScriptID;
eventScript = start_script(&EVS_Player_HandleEvent, EVT_PRIORITY_A, EVT_FLAG_RUN_IMMEDIATELY);
player->handleEventScript = eventScript;
player->handleEventScriptID = eventScript->id;
eventScript->owner1.actor = NULL;
if (oldOnHitScript != NULL) {
kill_script_by_ID(oldOnHitID);
}
}
// Determines whether an attack from the player will hit an enemy or
HitResult calc_player_test_enemy(void) {
BattleStatus* battleStatus = &gBattleStatus;
Actor* player = battleStatus->playerActor;
ActorState* state = &player->state;
s32 targetActorID = battleStatus->curTargetID;
s32 targetPartIdx = battleStatus->curTargetPart;
Actor* target;
ActorPart* targetPart;
battleStatus->curTargetID2 = battleStatus->curTargetID;
battleStatus->curTargetPart2 = battleStatus->curTargetPart;
target = get_actor(targetActorID);
if (target == NULL) {
return HIT_RESULT_HIT;
}
targetPart = get_actor_part(target, targetPartIdx);
ASSERT(targetPart != NULL);
if (targetPart->eventFlags & ACTOR_EVENT_FLAG_ILLUSORY) {
return HIT_RESULT_MISS;
}
if (target->transparentStatus == STATUS_KEY_TRANSPARENT
|| (targetPart->eventFlags & ACTOR_EVENT_FLAG_BURIED && !(battleStatus->curAttackElement & DAMAGE_TYPE_QUAKE))
) {
return HIT_RESULT_MISS;
}
if (target->stoneStatus == STATUS_KEY_STONE) {
sfx_play_sound_at_position(SOUND_IMMUNE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
return HIT_RESULT_IMMUNE;
}
if ((battleStatus->curAttackElement & DAMAGE_TYPE_JUMP)
&& (targetPart->eventFlags & ACTOR_EVENT_FLAG_SPIKY_TOP)
&& !player_team_is_ability_active(player, ABILITY_SPIKE_SHIELD))
{
sfx_play_sound_at_position(SOUND_HIT_SPIKE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
return HIT_RESULT_LANDED_ON_SPIKE;
}
if (!(battleStatus->curAttackElement & (DAMAGE_TYPE_NO_CONTACT | DAMAGE_TYPE_JUMP))
&& (targetPart->eventFlags & ACTOR_EVENT_FLAG_SPIKY_FRONT)
&& (!(battleStatus->curAttackEventSuppression & SUPPRESS_EVENT_SPIKY_FRONT)
&& !player_team_is_ability_active(player, ABILITY_SPIKE_SHIELD)))
{
sfx_play_sound_at_position(SOUND_HIT_SPIKE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
dispatch_hazard_event_player(1, EVENT_SPIKE_CONTACT);
dispatch_event_actor(target, EVENT_SPIKE_TAUNT);
return HIT_RESULT_BACKFIRE;
}
if (player->staticStatus != STATUS_KEY_STATIC && target->staticStatus == STATUS_KEY_STATIC) {
return HIT_RESULT_HIT_STATIC;
}
return HIT_RESULT_HIT;
}
HitResult calc_player_damage_enemy(void) {
BattleStatus* battleStatus = &gBattleStatus;
Actor* player = battleStatus->playerActor;
s32 currentTargetID = battleStatus->curTargetID;
s32 currentTargetPartID = battleStatus->curTargetPart;
ActorState* state;
Evt* evt;
Actor* target;
ActorPart* targetPart;
s32 hitResult;
s32 currentAttackDamage;
s32 targetDefense;
s32 dispatchEvent;
s32 partImmuneToElement;
s32 canBeShocked;
s32 missedAllOrNothing;
s32 isFireDamage;
s32 isShockDamage;
s32 isWaterDamage;
s32 isIceDamage;
s32 wasSpecialHit;
s32 wasStatusInflicted;
s32 attackFxType;
canBeShocked = false;
isFireDamage = false;
isWaterDamage = false;
isShockDamage = false;
isIceDamage = false;
wasSpecialHit = false;
partImmuneToElement = false;
wasStatusInflicted = false;
missedAllOrNothing = false;
battleStatus->wasStatusInflicted = false;
battleStatus->lastAttackDamage = 0;
battleStatus->attackerActorID = player->actorID;
battleStatus->curTargetID2 = battleStatus->curTargetID;
battleStatus->curTargetPart2 = battleStatus->curTargetPart;
target = get_actor(currentTargetID);
state = &player->state;
if (target == NULL) {
return HIT_RESULT_HIT;
}
targetPart = get_actor_part(target, currentTargetPartID);
ASSERT(targetPart != NULL);
target->lastDamageTaken = 0;
if (gBattleStatus.flags1 & BS_FLAGS1_FORCE_IMMUNE_HIT) {
hitResult = HIT_RESULT_NO_DAMAGE;
dispatchEvent = EVENT_ZERO_DAMAGE;
} else {
if (player_team_is_ability_active(player, ABILITY_ICE_POWER)) {
if (!(battleStatus->curAttackElement & DAMAGE_TYPE_NO_CONTACT)) {
battleStatus->curAttackElement |= DAMAGE_TYPE_ICE;
}
}
if (targetPart->eventFlags & ACTOR_EVENT_FLAG_ILLUSORY
|| target->transparentStatus == STATUS_KEY_TRANSPARENT
|| (targetPart->eventFlags & ACTOR_EVENT_FLAG_BURIED && !(battleStatus->curAttackElement & DAMAGE_TYPE_QUAKE))
) {
return HIT_RESULT_MISS;
}
if (target->stoneStatus == STATUS_KEY_STONE) {
sfx_play_sound_at_position(SOUND_IMMUNE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
show_immune_bonk(state->goalPos.x, state->goalPos.y, state->goalPos.z, 0, 1, 1);
show_next_damage_popup(state->goalPos.x, state->goalPos.y, state->goalPos.z, 0, 0);
if (gBattleStatus.flags1 & (BS_FLAGS1_NICE_HIT | BS_FLAGS1_SUPER_HIT)) {
return HIT_RESULT_NICE;
} else {
return HIT_RESULT_HIT;
}
}
if (targetPart->elementalImmunities & battleStatus->curAttackElement) {
partImmuneToElement = true;
}
// check jumping on spiky enemy
if ((battleStatus->curAttackElement & DAMAGE_TYPE_JUMP)
&& (targetPart->eventFlags & ACTOR_EVENT_FLAG_SPIKY_TOP)
&& !player_team_is_ability_active(player, ABILITY_SPIKE_SHIELD))
{
sfx_play_sound_at_position(SOUND_HIT_SPIKE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
dispatch_hazard_event_player(1, EVENT_SPIKE_CONTACT);
dispatch_event_actor(target, EVENT_SPIKE_TAUNT);
return HIT_RESULT_BACKFIRE;
}
// check touching fiery enemy and explode on contact
if (!(battleStatus->curAttackElement & (DAMAGE_TYPE_NO_CONTACT | DAMAGE_TYPE_SMASH))) {
if (targetPart->eventFlags & ACTOR_EVENT_FLAG_EXPLODE_ON_CONTACT) {
sfx_play_sound_at_position(SOUND_HIT_PLAYER_FIRE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
dispatch_hazard_event_player(1, EVENT_BURN_CONTACT);
dispatch_event_actor(target, EVENT_EXPLODE_TRIGGER);
return HIT_RESULT_BACKFIRE;
}
if (targetPart->eventFlags & ACTOR_EVENT_FLAG_FIREY
&& !(battleStatus->curAttackEventSuppression & SUPPRESS_EVENT_BURN_CONTACT)
&& !(player_team_is_ability_active(player, ABILITY_FIRE_SHIELD))
&& !(player_team_is_ability_active(player, ABILITY_ICE_POWER))
) {
sfx_play_sound_at_position(SOUND_HIT_PLAYER_FIRE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
dispatch_hazard_event_player(1, EVENT_BURN_CONTACT);
dispatch_event_actor(target, EVENT_BURN_TAUNT);
return HIT_RESULT_BACKFIRE;
}
}
// check explode on ignition
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS
&& battleStatus->curAttackElement & DAMAGE_TYPE_FIRE
&& targetPart->eventFlags & (ACTOR_EVENT_FLAG_FIRE_EXPLODE | ACTOR_EVENT_FLAG_EXPLODE_ON_IGNITION)
) {
sfx_play_sound_at_position(SOUND_HIT_PLAYER_FIRE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
dispatch_event_actor(target, EVENT_EXPLODE_TRIGGER);
if (gBattleStatus.flags1 & (BS_FLAGS1_NICE_HIT | BS_FLAGS1_SUPER_HIT)) {
return HIT_RESULT_NICE;
} else {
return HIT_RESULT_HIT;
}
}
// unknown alternate spiky #1
if (!(battleStatus->curAttackElement & (DAMAGE_TYPE_NO_CONTACT | DAMAGE_TYPE_SMASH))
&& targetPart->eventFlags & ACTOR_EVENT_FLAG_ALT_SPIKY
&& !(battleStatus->curAttackEventSuppression & SUPPRESS_EVENT_ALT_SPIKY)
&& !player_team_is_ability_active(player, ABILITY_SPIKE_SHIELD)
) {
sfx_play_sound_at_position(SOUND_HIT_SPIKE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
dispatch_hazard_event_player(1, EVENT_SPIKE_CONTACT);
dispatch_event_actor(target, EVENT_SPIKE_TAUNT);
return HIT_RESULT_BACKFIRE;
}
if (battleStatus->curAttackElement & DAMAGE_TYPE_FIRE) {
fx_ring_blast(0, state->goalPos.x, state->goalPos.y, state->goalPos.z * 5.0f, 1.0f, 24);
isFireDamage = true;
}
if (battleStatus->curAttackElement & DAMAGE_TYPE_SHOCK) {
apply_shock_effect(target);
isShockDamage = true;
}
if (battleStatus->curAttackElement & DAMAGE_TYPE_WATER) {
fx_water_splash(0, state->goalPos.x, state->goalPos.y, state->goalPos.z + 5.0f, 1.0f, 24);
isWaterDamage = true;
}
if (battleStatus->curAttackElement & DAMAGE_TYPE_ICE) {
fx_big_snowflakes(0, state->goalPos.x, state->goalPos.y, state->goalPos.z + 5.0f);
isIceDamage = true;
}
attackFxType = player_team_is_ability_active(player, ABILITY_ATTACK_FX);
if (attackFxType) {
fx_breaking_junk(0, state->goalPos.x, state->goalPos.y, state->goalPos.z + 5.0f, 1.0f, 30);
switch (attackFxType) {
case 1:
sfx_play_sound_at_position(SOUND_LIFE_SHROOM_CHIME, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
break;
case 2:
sfx_play_sound_at_position(SOUND_PLANTS_BELL, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
break;
case 3:
sfx_play_sound_at_position(SOUND_SLIDE_WHISTLE_OUT, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
break;
case 4:
sfx_play_sound_at_position(SOUND_YOSHI, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
break;
case 5:
sfx_play_sound_at_position(SOUND_HIT_WHACKA, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
break;
case 6:
sfx_play_sound_at_position(SOUND_FLOWERS_LAUGH, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
break;
}
}
if (!is_ability_active(ABILITY_ZAP_TAP)
&& player->staticStatus != STATUS_KEY_STATIC
&& (target->staticStatus == STATUS_KEY_STATIC || targetPart->eventFlags & ACTOR_EVENT_FLAG_ELECTRIFIED)
&& !(battleStatus->curAttackElement & (DAMAGE_TYPE_NO_CONTACT | DAMAGE_TYPE_SHOCK))
&& !(battleStatus->curAttackEventSuppression & SUPPRESS_EVENT_SHOCK_CONTACT)
) {
gBattleStatus.flags1 |= BS_FLAGS1_TRIGGER_EVENTS;
canBeShocked = true;
}
if (targetPart->eventFlags & (ACTOR_EVENT_FLAG_STAR_ROD_ENCHANTED | ACTOR_EVENT_FLAG_ENCHANTED)) {
battleStatus->curAttackElement &= ~DAMAGE_TYPE_IGNORE_DEFENSE;
}
targetDefense = get_defense(target, targetPart->defenseTable, battleStatus->curAttackElement);
if (!(battleStatus->curAttackElement & DAMAGE_TYPE_IGNORE_DEFENSE)) {
targetDefense += target->defenseBoost;
}
if (targetPart->eventFlags & ACTOR_EVENT_FLAG_EXTREME_DEFENSE) {
targetDefense += 127;
}
currentAttackDamage = battleStatus->curAttackDamage;
currentAttackDamage += count_power_plus(battleStatus->curAttackElement);
if (battleStatus->merleeAttackBoost > 0
&& (gBattleStatus.flags1 & BS_FLAGS1_INCLUDE_POWER_UPS || battleStatus->curAttackElement & DAMAGE_TYPE_JUMP)
) {
currentAttackDamage += battleStatus->merleeAttackBoost;
}
if (battleStatus->jumpCharge && battleStatus->curAttackElement & DAMAGE_TYPE_JUMP) {
currentAttackDamage += battleStatus->jumpCharge;
gBattleStatus.flags1 &= ~BS_FLAGS1_JUMP_CHARGED;
}
if (battleStatus->hammerCharge && battleStatus->curAttackElement & (DAMAGE_TYPE_QUAKE_HAMMER | DAMAGE_TYPE_THROW | DAMAGE_TYPE_SMASH)) {
currentAttackDamage += battleStatus->hammerCharge;
gBattleStatus.flags1 &= ~BS_FLAGS1_HAMMER_CHARGED;
}
if (battleStatus->unk_98 != 0) {
currentAttackDamage += 2;
}
if (player_team_is_ability_active(player, ABILITY_BERSERKER)) {
currentAttackDamage += 2;
}
if (player_team_is_ability_active(player, ABILITY_P_UP_D_DOWN)) {
currentAttackDamage++;
}
if (player_team_is_ability_active(player, ABILITY_P_DOWN_D_UP)) {
currentAttackDamage--;
}
if (battleStatus->turboChargeTurnsLeft != 0) {
currentAttackDamage++;
}
currentAttackDamage += player->attackBoost;
if (player_team_is_ability_active(player, ABILITY_HP_DRAIN)) {
battleStatus->hpDrainCount++;
currentAttackDamage--;
if (currentAttackDamage < 0) {
battleStatus->hpDrainCount += currentAttackDamage;
}
gBattleStatus.flags2 |= BS_FLAGS2_HAS_DRAINED_HP;
if (battleStatus->hpDrainCount > 5) {
battleStatus->hpDrainCount = 5;
}
}
if (player_team_is_ability_active(player, ABILITY_MEGA_HP_DRAIN)) {
battleStatus->hpDrainCount += 2;
currentAttackDamage -= 2;
if (currentAttackDamage < 0) {
battleStatus->hpDrainCount += currentAttackDamage;
}
gBattleStatus.flags2 |= BS_FLAGS2_HAS_DRAINED_HP;
if (battleStatus->hpDrainCount > 5) {
battleStatus->hpDrainCount = 5;
}
}
if (gBattleStatus.flags2 & BS_FLAGS2_HAS_RUSH
&& (gBattleStatus.flags1 & BS_FLAGS1_INCLUDE_POWER_UPS || battleStatus->curAttackElement & DAMAGE_TYPE_JUMP)
) {
if (battleStatus->rushFlags & RUSH_FLAG_POWER) {
currentAttackDamage += 2;
}
if (battleStatus->rushFlags & RUSH_FLAG_MEGA) {
currentAttackDamage += 4;
}
fx_radial_shimmer(9, state->goalPos.x, state->goalPos.y, state->goalPos.z, 0.5f, 20);
}
if (!(gBattleStatus.flags2 & BS_FLAGS2_IS_FIRST_STRIKE)
&& player_team_is_ability_active(player, ABILITY_ALL_OR_NOTHING)
) {
currentAttackDamage++;
if (!(gBattleStatus.flags1 & (BS_FLAGS1_NICE_HIT | BS_FLAGS1_SUPER_HIT))) {
missedAllOrNothing = true;
currentAttackDamage = 0;
#if !VERSION_JP
targetDefense = 0;
#endif
gBattleStatus.flags1 &= ~BS_FLAGS1_NICE_HIT;
gBattleStatus.flags1 &= ~BS_FLAGS1_SUPER_HIT;
gBattleStatus.flags1 &= ~BS_FLAGS1_INCLUDE_POWER_UPS;
gBattleStatus.flags1 |= BS_FLAGS1_TRIGGER_EVENTS;
}
}
if (player->debuff == STATUS_KEY_SHRINK) {
if (currentAttackDamage > 0) {
currentAttackDamage /= 2;
if (currentAttackDamage == 0) {
currentAttackDamage = 1;
}
}
}
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS
&& battleStatus->curAttackElement & DAMAGE_TYPE_BLAST
&& targetPart->eventFlags & ACTOR_EVENT_FLAG_EXPLODE_ON_IGNITION
) {
targetDefense = 0;
currentAttackDamage = target->curHP;
}
if (battleStatus->curAttackElement & DAMAGE_TYPE_STATUS_ALWAYS_HITS) {
targetDefense = 0;
currentAttackDamage = 0;
}
if (currentAttackDamage > 99) {
currentAttackDamage = 99;
}
if (currentAttackDamage < 0) {
targetDefense = 0;
}
target->hpChangeCounter = 0;
currentAttackDamage -= targetDefense;
if (currentAttackDamage < 0) {
currentAttackDamage = 0;
}
if (battleStatus->curAttackElement & DAMAGE_TYPE_POWER_BOUNCE && currentAttackDamage > 0) {
currentAttackDamage += battleStatus->powerBounceCounter;
if (currentAttackDamage < 1) {
currentAttackDamage = 1;
}
}
battleStatus->lastAttackDamage = 0;
if (currentAttackDamage < 1) {
target->hpChangeCounter = 0;
hitResult = HIT_RESULT_NO_DAMAGE;
if (!(battleStatus->curAttackElement & DAMAGE_TYPE_STATUS_ALWAYS_HITS)) {
dispatchEvent = EVENT_ZERO_DAMAGE;
sfx_play_sound_at_position(SOUND_IMMUNE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
} else {
if (target->curHP < 1) {
dispatchEvent = EVENT_DEATH;
} else {
dispatchEvent = EVENT_ZERO_DAMAGE;
}
}
battleStatus->lastAttackDamage = 0;
} else {
target->damageCounter += currentAttackDamage;
dispatchEvent = EVENT_HIT_COMBO;
hitResult = HIT_RESULT_HIT;
target->hpChangeCounter -= currentAttackDamage;
if (!(targetPart->flags & ACTOR_PART_FLAG_DAMAGE_IMMUNE)
&& !(gBattleStatus.flags1 & BS_FLAGS1_TUTORIAL_BATTLE)
&& !partImmuneToElement
&& !(targetPart->targetFlags & ACTOR_PART_TARGET_NO_DAMAGE)
) {
target->curHP -= currentAttackDamage;
if (target->curHP < 1) {
target->curHP = 0;
dispatchEvent = EVENT_DEATH;
}
}
battleStatus->lastAttackDamage += currentAttackDamage;
target->lastDamageTaken = battleStatus->lastAttackDamage;
target->hpChangeCounter = 0;
}
if (targetPart->flags & ACTOR_PART_FLAG_DAMAGE_IMMUNE) {
if (!is_ability_active(ABILITY_ZAP_TAP)
&& player->staticStatus != STATUS_KEY_STATIC
&& (target->staticStatus == STATUS_KEY_STATIC || (targetPart->eventFlags & ACTOR_EVENT_FLAG_ELECTRIFIED))
&& !(battleStatus->curAttackElement & DAMAGE_TYPE_NO_CONTACT)
&& !(battleStatus->curAttackEventSuppression & SUPPRESS_EVENT_SHOCK_CONTACT)
&& !(battleStatus->curAttackElement & DAMAGE_TYPE_SHOCK)
) {
sfx_play_sound_at_position(SOUND_HIT_PLAYER_SHOCK, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
apply_shock_effect(player);
dispatch_hazard_event_player(1, EVENT_SHOCK_HIT);
return HIT_RESULT_BACKFIRE;
} else {
if (!(gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS)) {
dispatchEvent = EVENT_ZERO_DAMAGE;
} else {
dispatchEvent = EVENT_IMMUNE;
}
sfx_play_sound_at_position(SOUND_IMMUNE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
dispatch_event_actor(target, dispatchEvent);
show_immune_bonk(state->goalPos.x, state->goalPos.y, state->goalPos.z, 0, 1, 3);
if (gBattleStatus.flags1 & (BS_FLAGS1_NICE_HIT | BS_FLAGS1_SUPER_HIT)) {
return HIT_RESULT_NICE;
} else {
return HIT_RESULT_HIT;
}
}
}
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS) {
if (battleStatus->curAttackElement & DAMAGE_TYPE_FEAR
&& rand_int(99) < (target->actorBlueprint->escapeChance * battleStatus->statusChance) / 100
&& (target->debuff != STATUS_KEY_FEAR
&& target->debuff != STATUS_KEY_DIZZY
&& target->debuff != STATUS_KEY_PARALYZE
&& target->debuff != STATUS_KEY_SLEEP
&& target->debuff != STATUS_KEY_FROZEN
&& target->debuff != STATUS_KEY_STOP)
&& !(target->flags & ACTOR_FLAG_FLIPPED)
) {
dispatch_event_actor(target, EVENT_SCARE_AWAY);
if (gBattleStatus.flags1 & (BS_FLAGS1_NICE_HIT | BS_FLAGS1_SUPER_HIT)) {
return HIT_RESULT_NICE;
} else {
return HIT_RESULT_HIT;
}
}
}
}
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS) {
if (dispatchEvent == EVENT_HIT_COMBO) {
dispatchEvent = EVENT_HIT;
}
if (dispatchEvent == EVENT_ZERO_DAMAGE) {
dispatchEvent = EVENT_IMMUNE;
}
if (target->curHP < 1) {
if (dispatchEvent == EVENT_IMMUNE) {
dispatchEvent = EVENT_DEATH;
}
}
} else if (dispatchEvent == EVENT_DEATH) {
dispatchEvent = EVENT_HIT_COMBO;
}
if (!(gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS)) {
clear_part_pal_adjustment(targetPart);
}
// check for special case damage events
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS) {
// if damage is from Spin Smash, convert generic events to Spin Smash specific events
if (battleStatus->curAttackElement & DAMAGE_TYPE_SPIN_SMASH) {
PlayerData* playerData = &gPlayerData;
if (target->actorBlueprint->spinSmashReq != 255
&& playerData->hammerLevel + 1 >= target->actorBlueprint->spinSmashReq
&& battleStatus->lastAttackDamage > 0
&& gBattleStatus.flags1 & BS_FLAGS1_NICE_HIT
) {
if (dispatchEvent == EVENT_HIT_COMBO) {
dispatchEvent = EVENT_SPIN_SMASH_HIT;
}
if (dispatchEvent == EVENT_HIT) {
dispatchEvent = EVENT_SPIN_SMASH_HIT;
}
if (dispatchEvent == EVENT_ZERO_DAMAGE) {
dispatchEvent = EVENT_SPIN_SMASH_HIT;
}
if (dispatchEvent == EVENT_IMMUNE) {
dispatchEvent = EVENT_SPIN_SMASH_HIT;
}
if (dispatchEvent == EVENT_DEATH) {
dispatchEvent = EVENT_SPIN_SMASH_DEATH;
}
}
}
// if damage is from Power Bounce, convert generic events to Power Bounce specific events
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS
&& !(battleStatus->curAttackElement & DAMAGE_TYPE_NO_CONTACT)
&& targetPart->eventFlags & ACTOR_EVENT_FLAG_POWER_BOUNCE
) {
if (dispatchEvent == EVENT_HIT_COMBO) {
dispatchEvent = EVENT_POWER_BOUNCE_HIT;
}
if (dispatchEvent == EVENT_HIT) {
dispatchEvent = EVENT_POWER_BOUNCE_HIT;
}
if (dispatchEvent == EVENT_ZERO_DAMAGE) {
dispatchEvent = EVENT_POWER_BOUNCE_HIT;
}
if (dispatchEvent == EVENT_IMMUNE) {
dispatchEvent = EVENT_POWER_BOUNCE_HIT;
}
if (dispatchEvent == EVENT_DEATH) {
dispatchEvent = EVENT_POWER_BOUNCE_DEATH;
}
}
// try generating fall trigger events
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS
&& (battleStatus->curAttackElement & (DAMAGE_TYPE_POW | DAMAGE_TYPE_JUMP))
&& targetPart->eventFlags & ACTOR_EVENT_FLAG_GROUNDABLE
) {
if (dispatchEvent == EVENT_HIT) {
dispatchEvent = EVENT_FALL_TRIGGER;
}
if (dispatchEvent == EVENT_IMMUNE) {
dispatchEvent = EVENT_FALL_TRIGGER;
}
wasSpecialHit = true;
}
// try generating flip trigger events
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS
&& (battleStatus->curAttackElement & (DAMAGE_TYPE_QUAKE | DAMAGE_TYPE_POW | DAMAGE_TYPE_JUMP))
&& targetPart->eventFlags & ACTOR_EVENT_FLAG_FLIPABLE
) {
if (dispatchEvent == EVENT_HIT) {
dispatchEvent = EVENT_FLIP_TRIGGER;
}
if (dispatchEvent == EVENT_IMMUNE) {
dispatchEvent = EVENT_FLIP_TRIGGER;
}
if (!(target->flags & ACTOR_FLAG_FLIPPED)) {
wasSpecialHit = true;
}
}
}
// try generating flip trigger events
if (!(gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS)
&& battleStatus->curAttackElement & (DAMAGE_TYPE_QUAKE | DAMAGE_TYPE_POW | DAMAGE_TYPE_JUMP)
&& targetPart->eventFlags & ACTOR_EVENT_FLAG_FLIPABLE
) {
if (dispatchEvent == EVENT_HIT_COMBO) {
dispatchEvent = EVENT_FLIP_TRIGGER;
}
if (dispatchEvent == EVENT_ZERO_DAMAGE) {
dispatchEvent = EVENT_FLIP_TRIGGER;
}
if (!(target->flags & ACTOR_FLAG_FLIPPED)) {
wasSpecialHit = true;
}
}
// try generating shell crack events
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS
&& battleStatus->curAttackElement & DAMAGE_TYPE_SHELL_CRACK
&& targetPart->eventFlags & ACTOR_EVENT_FLAG_FLIPABLE
) {
if (dispatchEvent == EVENT_HIT) {
dispatchEvent = EVENT_SHELL_CRACK_HIT;
}
if (dispatchEvent == EVENT_IMMUNE) {
dispatchEvent = EVENT_SHELL_CRACK_HIT;
}
wasSpecialHit = true;
}
// try generating burn events
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS
&& (battleStatus->curAttackElement & (DAMAGE_TYPE_BLAST | DAMAGE_TYPE_FIRE))
) {
if (dispatchEvent == EVENT_HIT) {
dispatchEvent = EVENT_BURN_HIT;
}
if (dispatchEvent == EVENT_DEATH) {
dispatchEvent = EVENT_BURN_DEATH;
}
isFireDamage = true;
}
// try inflicting status effects
do { // TODO remove this do while
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS
&& battleStatus->lastAttackDamage >= 0
&& dispatchEvent != EVENT_DEATH
&& dispatchEvent != EVENT_SPIN_SMASH_DEATH
&& dispatchEvent != EVENT_EXPLODE_TRIGGER
&& !(targetPart->targetFlags & ACTOR_PART_TARGET_NO_DAMAGE)
) {
#define INFLICT_STATUS(STATUS_TYPE) \
if ((battleStatus->curAttackStatus & STATUS_FLAG_##STATUS_TYPE) && \
try_inflict_status(target, STATUS_KEY_##STATUS_TYPE, STATUS_TURN_MOD_##STATUS_TYPE)) { \
wasSpecialHit = true; \
wasStatusInflicted = true; \
} \
INFLICT_STATUS(SHRINK);
INFLICT_STATUS(POISON);
INFLICT_STATUS(STONE);
INFLICT_STATUS(SLEEP);
INFLICT_STATUS(STOP);
INFLICT_STATUS(STATIC);
INFLICT_STATUS(FEAR);
INFLICT_STATUS(PARALYZE);
INFLICT_STATUS(DIZZY);
#undef INFLICT_STATUS
if (wasStatusInflicted) {
if (dispatchEvent == EVENT_ZERO_DAMAGE) {
dispatchEvent = EVENT_HIT_COMBO;
}
if (dispatchEvent == EVENT_IMMUNE) {
dispatchEvent = EVENT_HIT;
}
}
}
} while (0);
battleStatus->wasStatusInflicted = wasStatusInflicted;
dispatch_event_actor(target, dispatchEvent);
if (!(target->flags & ACTOR_FLAG_NO_DMG_POPUP)) {
if (battleStatus->lastAttackDamage == 0) {
if (!wasSpecialHit && !wasStatusInflicted) {
show_immune_bonk(state->goalPos.x, state->goalPos.y, state->goalPos.z, 0, 1, 3);
}
} else if (!partImmuneToElement) {
if (battleStatus->curAttackElement & (DAMAGE_TYPE_MULTIPLE_POPUPS | DAMAGE_TYPE_SMASH)) {
show_next_damage_popup(state->goalPos.x, state->goalPos.y, state->goalPos.z, battleStatus->lastAttackDamage, 0);
} else {
show_primary_damage_popup(state->goalPos.x, state->goalPos.y, state->goalPos.z, battleStatus->lastAttackDamage, 0);
}
if (!(targetPart->targetFlags & ACTOR_PART_TARGET_NO_DAMAGE)) {
show_damage_fx(target, state->goalPos.x, state->goalPos.y, state->goalPos.z, battleStatus->lastAttackDamage);
}
}
}
if ((wasSpecialHit && gBattleStatus.flags1 & BS_FLAGS1_NICE_HIT) || gBattleStatus.flags1 & BS_FLAGS1_NICE_HIT) {
if (!(gBattleStatus.flags1 & BS_FLAGS1_NO_RATING)) {
if (player->actorTypeData1[5]) {
sfx_play_sound_at_position(player->actorTypeData1[5], SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
if (battleStatus->lastAttackDamage > 0) {
sfx_play_sound(SOUND_DAMAGE_STARS);
}
if (battleStatus->lastAttackDamage > 0 || ((battleStatus->curAttackElement & DAMAGE_TYPE_STATUS_ALWAYS_HITS) && wasSpecialHit)) {
if (!(battleStatus->curAttackElement & DAMAGE_TYPE_MULTI_BOUNCE)) {
show_action_rating(ACTION_RATING_NICE, target, state->goalPos.x, state->goalPos.y, state->goalPos.z);
} else {
show_action_rating(ACTION_RATING_NICE_SUPER_COMBO, target, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
}
}
}
if (missedAllOrNothing) {
show_action_rating(ACTION_RATING_MISS, target, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
if (gBattleStatus.flags1 & BS_FLAGS1_TRIGGER_EVENTS) {
func_80266970(target);
}
if ((battleStatus->lastAttackDamage > 0 || wasSpecialHit) && !partImmuneToElement) {
set_actor_flash_mode(target, 1);
if (isFireDamage) {
sfx_play_sound_at_position(SOUND_HIT_FIRE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
} else if (isShockDamage) {
sfx_play_sound_at_position(SOUND_HIT_SHOCK, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
} else if (isIceDamage) {
sfx_play_sound_at_position(SOUND_HIT_ICE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
} else {
sfx_play_sound_at_position(SOUND_HIT_NORMAL, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
}
if (battleStatus->lastAttackDamage < 1 && !wasSpecialHit && !canBeShocked || targetPart->flags & ACTOR_PART_FLAG_DAMAGE_IMMUNE) {
sfx_play_sound_at_position(SOUND_IMMUNE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
if (battleStatus->curAttackStatus & STATUS_FLAG_SLEEP && wasStatusInflicted) {
evt = start_script(&EVS_PlaySleepHitFX, EVT_PRIORITY_A, 0);
evt->varTable[0] = state->goalPos.x;
evt->varTable[1] = state->goalPos.y;
evt->varTable[2] = state->goalPos.z;
sfx_play_sound_at_position(SOUND_INFLICT_SLEEP, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
if (battleStatus->curAttackStatus & STATUS_FLAG_DIZZY && wasStatusInflicted) {
evt = start_script(&EVS_PlayDizzyHitFX, EVT_PRIORITY_A, 0);
evt->varTable[0] = state->goalPos.x;
evt->varTable[1] = state->goalPos.y;
evt->varTable[2] = state->goalPos.z;
sfx_play_sound_at_position(SOUND_INFLICT_STATUS, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
if (battleStatus->curAttackStatus & STATUS_FLAG_PARALYZE && wasStatusInflicted) {
evt = start_script(&EVS_PlayParalyzeHitFX, EVT_PRIORITY_A, 0);
evt->varTable[0] = state->goalPos.x;
evt->varTable[1] = state->goalPos.y;
evt->varTable[2] = state->goalPos.z;
sfx_play_sound_at_position(SOUND_INFLICT_STATUS, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
if (battleStatus->curAttackStatus & STATUS_FLAG_POISON && wasStatusInflicted) {
evt = start_script(&EVS_PlayPoisonHitFX, EVT_PRIORITY_A, 0);
evt->varTable[0] = state->goalPos.x;
evt->varTable[1] = state->goalPos.y;
evt->varTable[2] = state->goalPos.z;
sfx_play_sound_at_position(SOUND_INFLICT_STATUS, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
if (battleStatus->curAttackStatus & STATUS_FLAG_STOP && wasStatusInflicted) {
evt = start_script(&EVS_PlayStopHitFX, EVT_PRIORITY_A, 0);
evt->varTable[0] = state->goalPos.x;
evt->varTable[1] = state->goalPos.y;
evt->varTable[2] = state->goalPos.z;
sfx_play_sound_at_position(SOUND_INFLICT_STATUS, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
if (battleStatus->curAttackStatus & STATUS_FLAG_FROZEN && wasStatusInflicted) {
evt = start_script(&EVS_PlayFreezeHitFX, EVT_PRIORITY_A, 0);
evt->varTable[0] = state->goalPos.x;
evt->varTable[1] = state->goalPos.y;
evt->varTable[2] = state->goalPos.z;
evt->varTablePtr[3] = target;
sfx_play_sound_at_position(SOUND_HIT_PLAYER_ICE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
if (battleStatus->curAttackStatus & STATUS_FLAG_SHRINK && wasStatusInflicted) {
evt = start_script(&EVS_PlayShrinkHitFX, EVT_PRIORITY_A, 0);
evt->varTable[0] = state->goalPos.x;
evt->varTable[1] = state->goalPos.y;
evt->varTable[2] = state->goalPos.z;
evt->varTablePtr[3] = target;
sfx_play_sound_at_position(SOUND_INFLICT_STATUS, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
if (battleStatus->curAttackElement & DAMAGE_TYPE_SMASH && target->actorType == ACTOR_TYPE_GOOMNUT_TREE) {
sfx_play_sound_at_position(SOUND_SMACK_TREE, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
show_actor_health_bar(target);
if (gBattleStatus.flags1 & (BS_FLAGS1_NICE_HIT | BS_FLAGS1_SUPER_HIT)) {
if (hitResult == HIT_RESULT_HIT) {
hitResult = HIT_RESULT_NICE;
}
if (hitResult == HIT_RESULT_NO_DAMAGE) {
hitResult = HIT_RESULT_NICE_NO_DAMAGE;
}
}
if (!is_ability_active(ABILITY_ZAP_TAP)
&& (player->staticStatus != STATUS_KEY_STATIC)
&& (target->staticStatus == STATUS_KEY_STATIC || targetPart->eventFlags & ACTOR_EVENT_FLAG_ELECTRIFIED)
&& !(battleStatus->curAttackElement & (DAMAGE_TYPE_NO_CONTACT | DAMAGE_TYPE_SHOCK))
&& !(battleStatus->curAttackEventSuppression & SUPPRESS_EVENT_SHOCK_CONTACT)
) {
sfx_play_sound_at_position(SOUND_HIT_PLAYER_SHOCK, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
apply_shock_effect(player);
dispatch_hazard_event_player(1, EVENT_SHOCK_HIT);
return HIT_RESULT_BACKFIRE;
}
return hitResult;
}
bool dispatch_damage_event_player(s32 damageAmount, s32 event, bool noHitSound) {
BattleStatus* battleStatus = &gBattleStatus;
PlayerData* playerData = &gPlayerData;
Actor* player = battleStatus->playerActor;
ActorState* state = &player->state;
s32 oldHPChangeCounter;
s32 flags;
s32 dispatchEvent;
s32 oldPlayerHP;
s32 temp;
battleStatus->curAttackDamage = damageAmount;
temp = (s16)damageAmount; //TODO usage of temp here required to match
player->hpChangeCounter += temp;
temp = player->hpChangeCounter;
player->curHP = playerData->curHP;
player->damageCounter += temp;
player->hpChangeCounter -= temp;
battleStatus->lastAttackDamage = 0;
player->curHP -= temp;
battleStatus->damageTaken += temp;
oldPlayerHP = player->curHP;
dispatchEvent = event;
if (player->curHP < 1) {
battleStatus->lastAttackDamage += oldPlayerHP;
player->curHP = 0;
dispatchEvent = EVENT_DEATH;
}
battleStatus->lastAttackDamage += temp;
playerData->curHP = player->curHP;
if (dispatchEvent == EVENT_HIT_COMBO) {
dispatchEvent = EVENT_HIT;
}
if (dispatchEvent == EVENT_ZERO_DAMAGE) {
dispatchEvent = EVENT_IMMUNE;
}
if (dispatchEvent == EVENT_DEATH) {
if (event == EVENT_SPIKE_CONTACT) {
dispatchEvent = EVENT_SPIKE_DEATH;
}
if (event == EVENT_BURN_CONTACT) {
dispatchEvent = EVENT_BURN_DEATH;
}
if (event == EVENT_SHOCK_HIT) {
dispatchEvent = EVENT_SHOCK_DEATH;
}
}
if (!noHitSound) {
set_goal_pos_to_part(state, ACTOR_PLAYER, 0);
sfx_play_sound_at_position(SOUND_HIT_NORMAL, SOUND_SPACE_DEFAULT, state->goalPos.x, state->goalPos.y, state->goalPos.z);
}
show_next_damage_popup(state->goalPos.x, state->goalPos.y, state->goalPos.z, battleStatus->lastAttackDamage, 1);
show_damage_fx(player, state->goalPos.x, state->goalPos.y, state->goalPos.z, battleStatus->lastAttackDamage);
if (battleStatus->lastAttackDamage > 0) {
set_actor_flash_mode(player, 1);
}
flags = (gBattleStatus.flags1 & (BS_FLAGS1_NICE_HIT | BS_FLAGS1_SUPER_HIT)) != 0;
dispatch_event_player(dispatchEvent);
return flags;
}
// damage received from "damage over time" effects (only used for poison)
s32 dispatch_damage_tick_event_player(s32 damageAmount, s32 event) {
BattleStatus* battleStatus = &gBattleStatus;
battleStatus->curAttackElement = ELEMENT_END;
battleStatus->curDamageSource = DMG_SRC_DEFAULT;
return dispatch_damage_event_player(damageAmount, event, false);
}
// damage received from contact hazards
bool dispatch_hazard_event_player(s32 damageAmount, s32 event) {
return dispatch_damage_event_player(damageAmount, event, true);
}
API_CALLABLE(GetMenuSelection) {
BattleStatus* battleStatus = &gBattleStatus;
Bytecode* args = script->ptrReadPos;
s32 outVar1 = *args++;
s32 outVar2 = *args++;
s32 outVar3 = *args++;
evt_set_variable(script, outVar1, battleStatus->moveCategory);
evt_set_variable(script, outVar2, battleStatus->moveArgument);
evt_set_variable(script, outVar3, battleStatus->selectedMoveID);
return ApiStatus_DONE2;
}
API_CALLABLE(PlayerHopToGoal) {
BattleStatus* battleStatus = &gBattleStatus;
Bytecode* args = script->ptrReadPos;
Actor* player = battleStatus->playerActor;
ActorState* playerState = &player->state;
f32 playerVel;
f32 x, y, z;
f32 goalX, goalY, goalZ;
f32 var_f8;
f64 playerSpeed;
if (isInitialCall) {
script->functionTemp[0] = false;
}
if (script->functionTemp[0] == 0) {
player->state.moveTime = evt_get_variable(script, *args++);
player->state.moveArcAmplitude = evt_get_variable(script, *args++);
script->functionTemp[1] = evt_get_variable(script, *args++);
player->state.curPos.x = player->curPos.x;
player->state.curPos.y = player->curPos.y;
player->state.curPos.z = player->curPos.z;
x = player->state.curPos.x;
y = player->state.curPos.y;
z = player->state.curPos.z;
goalX = player->state.goalPos.x;
goalY = player->state.goalPos.y;
goalZ = player->state.goalPos.z;
player->state.angle = atan2(x, z, goalX, goalZ);
player->state.dist = dist2D(x, z, goalX, goalZ);
y = goalY - y;
if (player->state.moveTime == 0) {
player->state.moveTime = player->state.dist / player->state.speed;
var_f8 = player->state.dist - (player->state.moveTime * player->state.speed);
} else {
player->state.speed = player->state.dist / player->state.moveTime;
var_f8 = player->state.dist - (player->state.moveTime * player->state.speed);
}
playerState->speed += var_f8 / playerState->moveTime;
playerState->vel = (playerState->acceleration * playerState->moveTime * 0.5f) + (y / playerState->moveTime);
set_actor_anim(0, 0, playerState->animJumpRise);
playerState->unk_24 = 90.0f;
playerState->unk_28 = 180 / playerState->moveTime;
playerState->unk_2C = playerState->goalPos.y;
if (script->functionTemp[1] != 2) {
sfx_play_sound_at_position(SOUND_LONG_PLAYER_JUMP, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
}
script->functionTemp[0] = true;
}
if (playerState->vel < 0.0f) {
set_actor_anim(0, 0, playerState->animJumpFall);
}
playerVel = playerState->vel;
switch (playerState->moveArcAmplitude) {
case 0:
break;
case 1:
if (playerState->curPos.y - playerState->unk_2C > 45.0f) {
playerVel *= 0.25f;
}
break;
case 2:
if (playerState->curPos.y - playerState->unk_2C > 54.9) {
playerVel *= 0.25f;
}
break;
}
playerState->curPos.y += playerVel;
playerState->vel -= playerState->acceleration;
playerSpeed = playerState->speed;
add_xz_vec3f(&playerState->curPos, playerSpeed + sin_rad(DEG_TO_RAD(playerState->unk_24)), playerState->angle);
playerState->unk_24 += playerState->unk_28;
playerState->unk_24 = clamp_angle(playerState->unk_24);
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y;
player->curPos.z = playerState->curPos.z;
playerState->moveTime--;
if (playerState->moveTime >= 0) {
return ApiStatus_BLOCK;
}
player->curPos.y = playerState->goalPos.y;
if (script->functionTemp[1] != 1) {
play_movement_dust_effects(2, player->curPos.x, player->curPos.y, player->curPos.z, player->yaw);
}
if (script->functionTemp[1] != 2) {
sfx_play_sound_at_position(SOUND_LAND_SOFTLY, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
}
return ApiStatus_DONE1;
}
API_CALLABLE(PlayerFallToGoal) {
Bytecode* args = script->ptrReadPos;
Actor* player = gBattleStatus.playerActor;
ActorState* state = &player->state;
f32 x, y, z;
f32 goalX, goalY, goalZ;
if (isInitialCall) {
script->functionTemp[0] = false;
}
if (!script->functionTemp[0]) {
s32 moveTime = evt_get_variable(script, *args++);
player->state.curPos.x = player->curPos.x;
player->state.curPos.y = player->curPos.y;
player->state.curPos.z = player->curPos.z;
x = player->state.curPos.x;
y = player->state.curPos.y;
z = player->state.curPos.z;
goalX = player->state.goalPos.x;
goalY = player->state.goalPos.y;
goalZ = player->state.goalPos.z;
state->moveTime = moveTime;
player->state.angle = atan2(x, z, goalX, goalZ);
player->state.dist = dist2D(x, z, goalX, goalZ);
y = goalY - y;
if (state->moveTime == 0) {
state->moveTime = state->dist / state->speed;
} else {
state->speed = state->dist / state->moveTime;
}
state->vel = 0.0f;
state->acceleration = ((y / state->moveTime) - state->vel) / (-state->moveTime * 0.5);
set_actor_anim(ACTOR_PLAYER, 0, state->animJumpRise);
script->functionTemp[0] = true;
}
if (state->vel < 0.0f) {
set_actor_anim(ACTOR_PLAYER, 0, state->animJumpFall);
}
state->curPos.y += state->vel;
state->vel -= state->acceleration;
add_xz_vec3f(&state->curPos, state->speed, state->angle);
player->curPos.x = state->curPos.x;
player->curPos.y = state->curPos.y;
player->curPos.z = state->curPos.z;
state->moveTime--;
if (state->moveTime < 0) {
player->curPos.x = state->goalPos.x;
player->curPos.y = state->goalPos.y;
player->curPos.z = state->goalPos.z;
play_movement_dust_effects(2, player->curPos.x, player->curPos.y, player->curPos.z, player->yaw);
sfx_play_sound_at_position(SOUND_LAND_SOFTLY, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
return ApiStatus_DONE1;
}
return ApiStatus_BLOCK;
}
API_CALLABLE(PlayerLandJump) {
Actor* player = gBattleStatus.playerActor;
ActorState* walkMovement = &player->state;
if (isInitialCall) {
script->functionTemp[0] = 0;
}
if (script->functionTemp[0] == 0) {
walkMovement->curPos.x = player->curPos.x;
walkMovement->curPos.y = player->curPos.y;
walkMovement->curPos.z = player->curPos.z;
script->functionTemp[0] = 1;
}
if (walkMovement->vel > 0.0f) {
if (walkMovement->animJumpRise != 0) {
set_actor_anim(0, 0, walkMovement->animJumpRise);
}
}
if (walkMovement->vel < 0.0f) {
if (walkMovement->animJumpFall != 0) {
set_actor_anim(0, 0, walkMovement->animJumpFall);
}
}
walkMovement->curPos.y += walkMovement->vel;
walkMovement->vel -= walkMovement->acceleration;
add_xz_vec3f(&walkMovement->curPos, walkMovement->speed, walkMovement->angle);
player->curPos.x = walkMovement->curPos.x;
player->curPos.y = walkMovement->curPos.y;
player->curPos.z = walkMovement->curPos.z;
if (player->curPos.y < 0.0f) {
player->curPos.y = 0.0f;
play_movement_dust_effects(2, player->curPos.x, player->curPos.y, player->curPos.z, player->yaw);
sfx_play_sound_at_position(SOUND_LAND_SOFTLY, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
return ApiStatus_DONE1;
}
return ApiStatus_BLOCK;
}
API_CALLABLE(PlayerRunToGoal) {
BattleStatus* battleStatus = &gBattleStatus;
Bytecode* args = script->ptrReadPos;
Actor* player = battleStatus->playerActor;
ActorState* playerState = &player->state;
f32 currentX, currentZ, goalX, goalZ;
if (isInitialCall) {
script->functionTemp[0] = false;
}
if (!script->functionTemp[0]) {
player->state.moveTime = evt_get_variable(script, *args++);
player->state.curPos.x = player->curPos.x;
player->state.curPos.y = player->curPos.y;
player->state.curPos.z = player->curPos.z;
goalX = player->state.goalPos.x;
goalZ = player->state.goalPos.z;
currentX = player->state.curPos.x;
currentZ = player->state.curPos.z;
player->state.angle = atan2(currentX, currentZ, goalX, goalZ);
player->state.dist = dist2D(currentX, currentZ, goalX, goalZ);
if (player->state.moveTime == 0) {
player->state.moveTime = player->state.dist / player->state.speed;
if (player->state.moveTime == 0) {
player->state.moveTime = 1;
}
player->state.speed += (player->state.dist - (player->state.moveTime * player->state.speed)) / player->state.moveTime;
} else {
player->state.speed = player->state.dist / player->state.moveTime;
}
playerState->dist = player->actorTypeData1b[0] + 1;
script->functionTemp[0] = true;
}
add_xz_vec3f(&playerState->curPos, playerState->speed, playerState->angle);
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y;
player->curPos.z = playerState->curPos.z;
if (playerState->speed < 4.0f) {
play_movement_dust_effects(0, player->curPos.x, player->curPos.y, player->curPos.z, player->yaw);
} else {
play_movement_dust_effects(1, player->curPos.x, player->curPos.y, player->curPos.z, player->yaw);
}
playerState->dist += playerState->speed;
if (playerState->dist > player->actorTypeData1b[0]) {
player->footStepCounter++;
playerState->dist = 0.0f;
if ((player->footStepCounter % 2) != 0) {
sfx_play_sound_at_position(SOUND_STEP_NORMAL1, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
} else {
sfx_play_sound_at_position(SOUND_STEP_NORMAL2, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
}
}
playerState->moveTime--;
if (playerState->moveTime <= 0) {
player->curPos.x = playerState->goalPos.x;
player->curPos.z = playerState->goalPos.z;
return ApiStatus_DONE2;
}
return ApiStatus_BLOCK;
}
API_CALLABLE(CancelablePlayerRunToGoal) {
BattleStatus* battleStatus = &gBattleStatus;
Bytecode* args = script->ptrReadPos;
Actor* player = battleStatus->playerActor;
ActorState* playerState = &player->state;
f32 currentX, currentZ, goalX, goalZ;
if (isInitialCall) {
script->functionTemp[0] = false;
}
if (!script->functionTemp[0]) {
player->state.moveTime = evt_get_variable(script, *args++);
script->functionTemp[1] = *args++;
player->state.curPos.x = player->curPos.x;
player->state.curPos.y = player->curPos.y;
player->state.curPos.z = player->curPos.z;
goalX = player->state.goalPos.x;
goalZ = player->state.goalPos.z;
currentX = player->state.curPos.x;
currentZ = player->state.curPos.z;
player->state.angle = atan2(currentX, currentZ, goalX, goalZ);
player->state.dist = dist2D(currentX, currentZ, goalX, goalZ);
if (player->state.moveTime == 0) {
player->state.moveTime = player->state.dist / player->state.speed;
player->state.speed += (player->state.dist - (player->state.moveTime * player->state.speed)) / player->state.moveTime;
} else {
player->state.speed = player->state.dist / player->state.moveTime;
}
playerState->dist = player->actorTypeData1b[0] + 1;
if (playerState->moveTime == 0) {
return ApiStatus_DONE2;
}
script->functionTemp[2] = false;
script->functionTemp[3] = 0;
script->functionTemp[0] = true;
}
add_xz_vec3f(&playerState->curPos, playerState->speed, playerState->angle);
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y;
player->curPos.z = playerState->curPos.z;
if (playerState->speed < 4.0f) {
play_movement_dust_effects(0, player->curPos.x, player->curPos.y, player->curPos.z, player->yaw);
} else {
play_movement_dust_effects(1, player->curPos.x, player->curPos.y, player->curPos.z, player->yaw);
}
playerState->dist += playerState->speed;
if (playerState->dist > player->actorTypeData1b[0]) {
player->footStepCounter++;
playerState->dist = 0.0f;
if ((player->footStepCounter % 2) != 0) {
sfx_play_sound_at_position(SOUND_STEP_NORMAL1, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
} else {
sfx_play_sound_at_position(SOUND_STEP_NORMAL2, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
}
}
if (script->functionTemp[3] > 12) {
if (!script->functionTemp[2]) {
if (!(battleStatus->curButtonsDown & BUTTON_A)) {
script->functionTemp[2] = true;
}
}
if (script->functionTemp[2]) {
if (battleStatus->curButtonsPressed & BUTTON_A) {
evt_set_variable(script, script->functionTemp[1], 1);
return ApiStatus_DONE2;
}
}
}
script->functionTemp[3]++;
playerState->moveTime--;
if (playerState->moveTime > 0) {
return ApiStatus_BLOCK;
}
player->curPos.x = playerState->goalPos.x;
player->curPos.z = playerState->goalPos.z;
evt_set_variable(script, script->functionTemp[1], 0);
return ApiStatus_DONE2;
}
API_CALLABLE(GetPlayerHP) {
evt_set_variable(script, *script->ptrReadPos, gPlayerData.curHP);
return ApiStatus_DONE2;
}
API_CALLABLE(PlayerDamageEnemy) {
BattleStatus* battleStatus = &gBattleStatus;
Bytecode* args = script->ptrReadPos;
s32 hitResultOutVar = *args++;
s32 flags;
Actor* target;
HitResult hitResult;
battleStatus->curAttackElement = *args++;
battleStatus->curAttackEventSuppression = *args++;
battleStatus->curAttackStatus = *args++;
battleStatus->curAttackDamage = evt_get_variable(script, *args++);
battleStatus->powerBounceCounter = 0;
flags = *args++;
if ((flags & BS_FLAGS1_INCLUDE_POWER_UPS) && (flags & BS_FLAGS1_TRIGGER_EVENTS)) {
gBattleStatus.flags1 |= BS_FLAGS1_INCLUDE_POWER_UPS;
gBattleStatus.flags1 |= BS_FLAGS1_TRIGGER_EVENTS;
} else if (flags & BS_FLAGS1_INCLUDE_POWER_UPS) {
gBattleStatus.flags1 |= BS_FLAGS1_INCLUDE_POWER_UPS;
gBattleStatus.flags1 &= ~BS_FLAGS1_TRIGGER_EVENTS;
} else if (flags & BS_FLAGS1_TRIGGER_EVENTS) {
gBattleStatus.flags1 &= ~BS_FLAGS1_INCLUDE_POWER_UPS;
gBattleStatus.flags1 |= BS_FLAGS1_TRIGGER_EVENTS;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_INCLUDE_POWER_UPS;
gBattleStatus.flags1 &= ~BS_FLAGS1_TRIGGER_EVENTS;
}
if (flags & BS_FLAGS1_NICE_HIT) {
gBattleStatus.flags1 |= BS_FLAGS1_NICE_HIT;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_NICE_HIT;
}
if (flags & BS_FLAGS1_SUPER_HIT) {
gBattleStatus.flags1 |= BS_FLAGS1_SUPER_HIT;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_SUPER_HIT;
}
if (flags & BS_FLAGS1_NO_RATING) {
gBattleStatus.flags1 |= BS_FLAGS1_NO_RATING;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_NO_RATING;
}
if (flags & BS_FLAGS1_FORCE_IMMUNE_HIT) {
gBattleStatus.flags1 |= BS_FLAGS1_FORCE_IMMUNE_HIT;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_FORCE_IMMUNE_HIT;
}
target = get_actor(script->owner1.actorID);
battleStatus->curTargetID = target->targetActorID;
battleStatus->curTargetPart = target->targetPartID;
battleStatus->statusChance = battleStatus->curAttackStatus;
if (battleStatus->statusChance == STATUS_KEY_NEVER) {
battleStatus->statusChance = 0;
}
battleStatus->statusDuration = (battleStatus->curAttackStatus & 0xF00) >> 8;
hitResult = calc_player_damage_enemy();
if (hitResult < 0) {
return ApiStatus_FINISH;
}
evt_set_variable(script, hitResultOutVar, hitResult);
if (!does_script_exist_by_ref(script)) {
return ApiStatus_FINISH;
}
return ApiStatus_DONE2;
}
API_CALLABLE(PlayerPowerBounceEnemy) {
BattleStatus* battleStatus = &gBattleStatus;
Bytecode* args = script->ptrReadPos;
s32 hitResultOutVar = *args++;
s32 flags;
Actor* target;
HitResult hitResult;
battleStatus->curAttackElement = *args++;
battleStatus->curAttackEventSuppression = *args++;
battleStatus->curAttackStatus = *args++;
battleStatus->curAttackDamage = evt_get_variable(script, *args++);
battleStatus->powerBounceCounter = evt_get_variable(script, *args++);
flags = *args++;
if ((flags & BS_FLAGS1_INCLUDE_POWER_UPS) && (flags & BS_FLAGS1_TRIGGER_EVENTS)) {
gBattleStatus.flags1 |= BS_FLAGS1_INCLUDE_POWER_UPS | BS_FLAGS1_TRIGGER_EVENTS;
} else if (flags & BS_FLAGS1_INCLUDE_POWER_UPS) {
gBattleStatus.flags1 |= BS_FLAGS1_INCLUDE_POWER_UPS;
gBattleStatus.flags1 &= ~BS_FLAGS1_TRIGGER_EVENTS;
} else if (flags & BS_FLAGS1_TRIGGER_EVENTS) {
gBattleStatus.flags1 &= ~BS_FLAGS1_INCLUDE_POWER_UPS;
gBattleStatus.flags1 |= BS_FLAGS1_TRIGGER_EVENTS;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_INCLUDE_POWER_UPS;
gBattleStatus.flags1 &= ~BS_FLAGS1_TRIGGER_EVENTS;
}
if (flags & BS_FLAGS1_NICE_HIT) {
gBattleStatus.flags1 |= BS_FLAGS1_NICE_HIT;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_NICE_HIT;
}
if (flags & BS_FLAGS1_SUPER_HIT) {
gBattleStatus.flags1 |= BS_FLAGS1_SUPER_HIT;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_SUPER_HIT;
}
if (flags & BS_FLAGS1_NO_RATING) {
gBattleStatus.flags1 |= BS_FLAGS1_NO_RATING;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_NO_RATING;
}
if (flags & BS_FLAGS1_FORCE_IMMUNE_HIT) {
gBattleStatus.flags1 |= BS_FLAGS1_FORCE_IMMUNE_HIT;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_FORCE_IMMUNE_HIT;
}
target = get_actor(script->owner1.actorID);
battleStatus->curTargetID = target->targetActorID;
battleStatus->curTargetPart = target->targetPartID;
battleStatus->statusChance = battleStatus->curAttackStatus;
if (battleStatus->statusChance == STATUS_KEY_NEVER) {
battleStatus->statusChance = 0;
}
battleStatus->statusDuration = (battleStatus->curAttackStatus & 0xF00) >> 8;
hitResult = calc_player_damage_enemy();
if (hitResult < 0) {
return ApiStatus_FINISH;
}
evt_set_variable(script, hitResultOutVar, hitResult);
if (!does_script_exist_by_ref(script)) {
return ApiStatus_FINISH;
}
return ApiStatus_DONE2;
}
API_CALLABLE(PlayerTestEnemy) {
BattleStatus* battleStatus = &gBattleStatus;
Bytecode* args = script->ptrReadPos;
s32 hitResultOutVar = *args++;
s32 flags;
Actor* target;
HitResult hitResult;
battleStatus->curAttackElement = *args++;
battleStatus->curAttackEventSuppression = *args++;
battleStatus->curAttackStatus = *args++;
battleStatus->curAttackDamage = evt_get_variable(script, *args++);
battleStatus->powerBounceCounter = 0;
flags = *args++;
if ((flags & BS_FLAGS1_INCLUDE_POWER_UPS) && (flags & BS_FLAGS1_TRIGGER_EVENTS)) {
gBattleStatus.flags1 |= BS_FLAGS1_INCLUDE_POWER_UPS | BS_FLAGS1_TRIGGER_EVENTS;
} else if (flags & BS_FLAGS1_INCLUDE_POWER_UPS) {
gBattleStatus.flags1 |= BS_FLAGS1_INCLUDE_POWER_UPS;
gBattleStatus.flags1 &= ~BS_FLAGS1_TRIGGER_EVENTS;
} else if (flags & BS_FLAGS1_TRIGGER_EVENTS) {
gBattleStatus.flags1 &= ~BS_FLAGS1_INCLUDE_POWER_UPS;
gBattleStatus.flags1 |= BS_FLAGS1_TRIGGER_EVENTS;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_INCLUDE_POWER_UPS;
gBattleStatus.flags1 &= ~BS_FLAGS1_TRIGGER_EVENTS;
}
if (flags & BS_FLAGS1_NICE_HIT) {
gBattleStatus.flags1 |= BS_FLAGS1_NICE_HIT;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_NICE_HIT;
}
if (flags & BS_FLAGS1_SUPER_HIT) {
gBattleStatus.flags1 |= BS_FLAGS1_SUPER_HIT;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_SUPER_HIT;
}
if (flags & BS_FLAGS1_NO_RATING) {
gBattleStatus.flags1 |= BS_FLAGS1_NO_RATING;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_NO_RATING;
}
if (flags & BS_FLAGS1_FORCE_IMMUNE_HIT) {
gBattleStatus.flags1 |= BS_FLAGS1_FORCE_IMMUNE_HIT;
} else {
gBattleStatus.flags1 &= ~BS_FLAGS1_FORCE_IMMUNE_HIT;
}
target = get_actor(script->owner1.actorID);
battleStatus->curTargetID = target->targetActorID;
battleStatus->curTargetPart = target->targetPartID;
battleStatus->statusChance = battleStatus->curAttackStatus;
if (battleStatus->statusChance == STATUS_KEY_NEVER) {
battleStatus->statusChance = 0;
}
battleStatus->statusDuration = (battleStatus->curAttackStatus & 0xF00) >> 8;
hitResult = calc_player_test_enemy();
if (hitResult < 0) {
return ApiStatus_FINISH;
}
evt_set_variable(script, hitResultOutVar, hitResult);
return ApiStatus_DONE2;
}
API_CALLABLE(DispatchDamagePlayerEvent) {
Bytecode* args = script->ptrReadPos;
s32 damageAmount = evt_get_variable(script, *args++);
if (dispatch_damage_tick_event_player(damageAmount, *args++) < 0) {
return ApiStatus_BLOCK;
}
if (does_script_exist_by_ref(script)) {
return ApiStatus_DONE2;
}
return ApiStatus_BLOCK;
}
API_CALLABLE(EnablePlayerBlur) {
s32 setting = evt_get_variable(script, *script->ptrReadPos);
if (setting == ACTOR_BLUR_DISABLE) {
disable_player_blur();
} else if (setting == ACTOR_BLUR_ENABLE) {
enable_player_blur();
} else {
reset_player_blur();
}
return ApiStatus_DONE2;
}
API_CALLABLE(ForceDisablePlayerBlur) {
force_disable_player_blur();
return ApiStatus_DONE2;
}
API_CALLABLE(ForceDisablePlayerBlurImmediately) {
force_disable_player_blur_immediately();
return ApiStatus_DONE2;
}
API_CALLABLE(PlayerBasicJumpToGoal) {
BattleStatus* battleStatus = &gBattleStatus;
Bytecode* args = script->ptrReadPos;
Actor* player = battleStatus->playerActor;
ActorState* playerState = &player->state;
f32 posX, posY, posZ;
f32 goalX, goalZ;
f32 temp;
f64 temp_f20_2;
f64 vel1, vel2;
f64 vel3, vel4;
f64 acc1, acc2;
f64 acc3, acc4;
enum {
BASIC_STATE_00 = 0,
BASIC_STATE_01 = 1,
BASIC_STATE_02 = 2,
BASIC_STATE_03 = 3,
};
if (isInitialCall) {
player->state.moveTime = evt_get_variable(script, *args++);
player->state.moveArcAmplitude = evt_get_variable(script, *args++);
script->functionTemp[1] = 0;
script->functionTemp[0] = BASIC_STATE_00;
if (player->state.moveArcAmplitude == 1) {
script->functionTemp[0] = BASIC_STATE_02;
}
}
if (script->functionTemp[0] == BASIC_STATE_00) {
playerState->curPos.x = player->curPos.x;
playerState->curPos.y = player->curPos.y;
playerState->curPos.z = player->curPos.z;
goalX = playerState->goalPos.x;
goalZ = playerState->goalPos.z;
posX = playerState->curPos.x;
posY = playerState->curPos.y;
posZ = playerState->curPos.z;
playerState->angle = atan2(posX, posZ, goalX, goalZ);
playerState->dist = dist2D(posX, posZ, goalX, goalZ);
if (playerState->moveTime == 0) {
playerState->moveTime = playerState->dist / playerState->speed;
temp = playerState->dist - (playerState->moveTime * playerState->speed);
} else {
playerState->speed = playerState->dist / playerState->moveTime;
temp = playerState->dist - (playerState->moveTime * playerState->speed);
}
if (playerState->moveTime == 0) {
return ApiStatus_DONE2;
}
playerState->velStep.x = (playerState->goalPos.x - playerState->curPos.x) / playerState->moveTime;
playerState->velStep.y = (playerState->goalPos.y - playerState->curPos.y) / playerState->moveTime;
playerState->velStep.z = (playerState->goalPos.z - playerState->curPos.z) / playerState->moveTime;
playerState->acceleration = PI_S / playerState->moveTime;
playerState->vel = 0.0f;
playerState->speed += temp / playerState->moveTime;
if (playerState->moveArcAmplitude < 3) {
temp = playerState->dist;
temp -= 20.0;
temp /= 6.0;
temp += 47.0;
playerState->bounceDivisor = temp;
playerState->unk_24 = 90.0f;
playerState->unk_28 = 360 / playerState->moveTime;
if (playerState->moveArcAmplitude == 2) {
playerState->bounceDivisor = temp * 1.12;
}
playerState->unk_18.x = 0.0f;
playerState->unk_18.y = 0.0f;
vel1 = playerState->vel;
acc1 = playerState->acceleration;
playerState->vel = vel1 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53 * acc1) + acc1);
} else {
temp = playerState->dist;
temp -= 20.0;
temp /= 6.0;
temp += 47.0;
playerState->bounceDivisor = temp;
playerState->unk_24 = 90.0f;
playerState->unk_28 = 360 / playerState->moveTime;
if (playerState->moveArcAmplitude == 4) {
playerState->bounceDivisor = temp * 1.25;
}
playerState->unk_18.x = 0.0f;
playerState->unk_18.y = 0.0f;
vel2 = playerState->vel;
acc2 = playerState->acceleration;
playerState->vel = vel2 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.8 * acc2) + acc2);
}
set_actor_anim(0, 0, playerState->animJumpRise);
sfx_play_sound_at_position(SOUND_LONG_PLAYER_JUMP, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
script->functionTemp[0] = BASIC_STATE_01;
}
switch (script->functionTemp[0]) {
case BASIC_STATE_01:
if (playerState->vel > PI_S / 2) {
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpFall);
}
playerState->curPos.x += playerState->velStep.x;
playerState->curPos.y += playerState->velStep.y;
playerState->curPos.z += playerState->velStep.z;
playerState->unk_18.x = player->curPos.y;
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y + (playerState->bounceDivisor * sin_rad(playerState->vel));
player->curPos.z = playerState->curPos.z;
if (playerState->goalPos.y > player->curPos.y && playerState->moveTime < 3) {
player->curPos.y = playerState->goalPos.y;
}
playerState->unk_18.y = player->curPos.y;
if (playerState->moveArcAmplitude < 3) {
vel3 = playerState->vel;
acc3 = playerState->acceleration;
playerState->vel = vel3 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53 * acc3) + acc3);
} else {
vel4 = playerState->vel;
acc4 = playerState->acceleration;
playerState->vel = vel4 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.8 * acc4) + acc4);
}
playerState->unk_24 += playerState->unk_28;
playerState->unk_24 = clamp_angle(playerState->unk_24);
playerState->moveTime--;
if (playerState->moveTime == 0) {
player->curPos.y = playerState->goalPos.y;
playerState->acceleration = 1.8f;
playerState->vel = -(playerState->unk_18.x - playerState->unk_18.y);
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpLand);
return ApiStatus_DONE1;
}
break;
case BASIC_STATE_02:
if (battleStatus->actionCommandMode == AC_MODE_NOT_LEARNED) {
return ApiStatus_DONE2;
}
playerState->moveTime = 1;
playerState->acceleration = 1.8f;
playerState->unk_24 = 90.0f;
playerState->vel = -(playerState->unk_18.x - playerState->unk_18.y);
playerState->bounceDivisor = fabsf(playerState->unk_18.x - playerState->unk_18.y) / 16.5;
playerState->unk_28 = 360 / playerState->moveTime;
playerState->curPos.x = player->curPos.x;
playerState->curPos.y = player->curPos.y;
playerState->curPos.z = player->curPos.z;
script->functionTemp[0] = BASIC_STATE_03;
// fallthrough
case BASIC_STATE_03:
temp_f20_2 = playerState->curPos.x;
playerState->curPos.x = temp_f20_2 + ((playerState->bounceDivisor * sin_rad(DEG_TO_RAD(playerState->unk_24))) / 33.0);
playerState->curPos.y -= (playerState->bounceDivisor * sin_rad(DEG_TO_RAD(playerState->unk_24)));
playerState->unk_24 += playerState->unk_28;
playerState->unk_24 = clamp_angle(playerState->unk_24);
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y;
player->curPos.z = playerState->curPos.z;
if (gBattleStatus.flags1 & BS_FLAGS1_2000) {
return ApiStatus_DONE2;
}
playerState->moveTime--;
if (playerState->moveTime == 0) {
return ApiStatus_DONE1;
}
break;
}
return ApiStatus_BLOCK;
}
API_CALLABLE(PlayerSuperJumpToGoal) {
Bytecode* args = script->ptrReadPos;
Actor* player = gBattleStatus.playerActor;
ActorState* playerState = &player->state;
f32 posX, posY, posZ;
f32 goalX, goalZ;
f32 temp;
f64 temp_f20;
f64 vel1, vel2;
f64 vel3, vel4;
f64 vel5, vel6;
f64 vel7, vel8;
f64 acc1, acc2;
f64 acc3, acc4;
f64 acc5, acc6;
f64 acc7, acc8;
enum {
SUPER_STATE_00 = 0,
SUPER_STATE_01 = 1,
SUPER_STATE_02 = 2,
SUPER_STATE_10 = 10,
SUPER_STATE_11 = 11,
SUPER_STATE_20 = 20,
SUPER_STATE_21 = 21,
};
if (isInitialCall) {
player->state.moveTime = evt_get_variable(script, *args++);
player->state.moveArcAmplitude = evt_get_variable(script, *args++);
script->functionTemp[0] = SUPER_STATE_00;
if (player->state.moveArcAmplitude == PLAYER_SUPER_JUMP_1 ||
player->state.moveArcAmplitude == PLAYER_SUPER_JUMP_5 ||
player->state.moveArcAmplitude == PLAYER_SUPER_JUMP_6)
{
script->functionTemp[0] = SUPER_STATE_10;
}
if (playerState->moveArcAmplitude == PLAYER_SUPER_JUMP_2) {
script->functionTemp[0] = SUPER_STATE_20;
}
}
switch (script->functionTemp[0]) {
case SUPER_STATE_00:
playerState->curPos.x = player->curPos.x;
playerState->curPos.y = player->curPos.y;
playerState->curPos.z = player->curPos.z;
goalX = playerState->goalPos.x;
goalZ = playerState->goalPos.z;
posX = playerState->curPos.x;
posY = playerState->curPos.y;
posZ = playerState->curPos.z;
playerState->angle = atan2(posX, posZ, goalX, goalZ);
playerState->dist = dist2D(posX, posZ, goalX, goalZ);
if (playerState->moveTime == 0) {
playerState->moveTime = playerState->dist / playerState->speed;
temp = playerState->dist - (playerState->moveTime * playerState->speed);
} else {
playerState->speed = playerState->dist / playerState->moveTime;
temp = playerState->dist - (playerState->moveTime * playerState->speed);
}
if (playerState->moveTime == 0) {
return ApiStatus_DONE2;
}
playerState->velStep.x = (playerState->goalPos.x - playerState->curPos.x) / playerState->moveTime;
playerState->velStep.y = (playerState->goalPos.y - playerState->curPos.y) / playerState->moveTime;
playerState->velStep.z = (playerState->goalPos.z - playerState->curPos.z) / playerState->moveTime;
playerState->acceleration = (PI_S / 2) / playerState->moveTime;
playerState->vel = 0.0f;
playerState->speed += temp / playerState->moveTime;
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpRise);
sfx_play_sound_at_position(SOUND_LONG_PLAYER_JUMP, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
playerState->unk_24 = 90.0f;
playerState->bounceDivisor = 45.0f;
playerState->unk_28 = 360 / playerState->moveTime;
if (playerState->moveArcAmplitude == 4) {
playerState->bounceDivisor = 56.25f;
}
playerState->unk_18.x = 0.0f;
playerState->unk_18.y = 0.0f;
if (playerState->moveArcAmplitude == 0) {
vel1 = playerState->vel;
acc1 = playerState->acceleration;
playerState->vel = (vel1 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53 * acc1) + acc1));
} else {
vel2 = playerState->vel;
acc2 = playerState->acceleration;
playerState->vel = (vel2 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.01 * acc2) + acc2));
}
script->functionTemp[0] = SUPER_STATE_01;
break;
case SUPER_STATE_10:
playerState->curPos.x = player->curPos.x;
playerState->curPos.y = player->curPos.y;
playerState->curPos.z = player->curPos.z;
goalX = playerState->goalPos.x;
goalZ = playerState->goalPos.z;
posX = playerState->curPos.x;
posY = playerState->curPos.y;
posZ = playerState->curPos.z;
playerState->angle = atan2(posX, posZ, goalX, goalZ);
playerState->dist = dist2D(posX, posZ, goalX, goalZ);
if (playerState->moveTime == 0) {
playerState->moveTime = playerState->dist / playerState->speed;
temp = playerState->dist - (playerState->moveTime * playerState->speed);
} else {
playerState->speed = playerState->dist / playerState->moveTime;
temp = playerState->dist - (playerState->moveTime * playerState->speed);
}
if (playerState->moveTime == 0) {
return ApiStatus_DONE2;
}
playerState->velStep.x = (playerState->goalPos.x - playerState->curPos.x) / playerState->moveTime;
playerState->velStep.y = (playerState->goalPos.y - playerState->curPos.y) / playerState->moveTime;
playerState->velStep.z = (playerState->goalPos.z - playerState->curPos.z) / playerState->moveTime;
playerState->vel = (PI_S / 2);
playerState->acceleration = (PI_S / 4) / (playerState->moveTime + 1);
playerState->speed += temp / playerState->moveTime;
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpLand);
playerState->unk_24 = 90.0f;
playerState->bounceDivisor = 45.0f;
playerState->unk_28 = (360 / playerState->moveTime);
if (playerState->moveArcAmplitude == 5) {
playerState->bounceDivisor = 56.25f;
}
playerState->unk_18.x = 0.0f;
playerState->unk_18.y = 0.0f;
if (playerState->moveArcAmplitude == 1) {
vel3 = playerState->vel;
acc3 = playerState->acceleration;
playerState->vel = (vel3 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53 * acc3) + acc3));
} else {
vel4 = playerState->vel;
acc4 = playerState->acceleration;
playerState->vel = (vel4 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.01 * acc4) + acc4));
}
playerState->curPos.y = player->curPos.y - playerState->bounceDivisor;
script->functionTemp[0] = SUPER_STATE_11;
break;
case SUPER_STATE_20:
playerState->moveTime = 1;
playerState->unk_24 = 90.0f;
playerState->bounceDivisor = (fabsf(playerState->unk_18.x - playerState->unk_18.y) / 16.5);
playerState->unk_28 = (360 / playerState->moveTime);
playerState->curPos.x = player->curPos.x;
playerState->curPos.y = player->curPos.y;
playerState->curPos.z = player->curPos.z;
script->functionTemp[0] = SUPER_STATE_21;
break;
}
switch (script->functionTemp[0]) {
case SUPER_STATE_01:
if (playerState->moveArcAmplitude == 0) {
vel5 = playerState->vel;
acc5 = playerState->acceleration;
playerState->vel = (vel5 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53 * acc5) + acc5));
} else {
vel6 = playerState->vel;
acc6 = playerState->acceleration;
playerState->vel = (vel6 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.01 * acc6) + acc6));
}
playerState->curPos.x += playerState->velStep.x;
playerState->curPos.y += playerState->velStep.y;
playerState->curPos.z += playerState->velStep.z;
playerState->unk_18.x = player->curPos.y;
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y + (playerState->bounceDivisor * sin_rad(sin_rad(sin_rad(playerState->vel) * (PI_S / 2)) * (PI_S / 2)));
player->curPos.z = playerState->curPos.z;
playerState->unk_18.y = player->curPos.y;
playerState->unk_24 += playerState->unk_28;
playerState->unk_24 = clamp_angle(playerState->unk_24);
playerState->moveTime--;
if (playerState->moveTime == 0) {
sfx_play_sound_at_position(SOUND_LONG_PLAYER_JUMP, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpFall);
player->rotPivotOffset.y = 14;
player->rot.z -= 66.0f;
playerState->moveTime = 7;
script->functionTemp[0] = SUPER_STATE_02;
}
break;
case SUPER_STATE_02:
player->rotPivotOffset.y = 14;
player->rot.z -= 66.0f;
playerState->moveTime--;
if (playerState->moveTime == 0) {
player->rot.z = 0.0f;
player->rotPivotOffset.y = 0;
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpLand);
return ApiStatus_DONE1;
}
break;
case SUPER_STATE_11:
playerState->curPos.x += playerState->velStep.x;
playerState->curPos.y += playerState->velStep.y;
playerState->curPos.z += playerState->velStep.z;
playerState->unk_18.x = player->curPos.y;
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y + (playerState->bounceDivisor * sin_rad(playerState->vel));
player->curPos.z = playerState->curPos.z;
if (playerState->goalPos.y > player->curPos.y) {
player->curPos.y = playerState->goalPos.y;
}
playerState->unk_18.y = player->curPos.y;
if (playerState->moveArcAmplitude == 1) {
vel7 = playerState->vel;
acc7 = playerState->acceleration;
playerState->vel = (vel7 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53 * acc7) + acc7));
} else {
vel8 = playerState->vel;
acc8 = playerState->acceleration;
playerState->vel = (vel8 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.01 * acc8) + acc8));
}
playerState->unk_24 += playerState->unk_28;
playerState->unk_24 = clamp_angle(playerState->unk_24);
playerState->moveTime--;
if (playerState->moveTime == 0) {
player->curPos.y = playerState->goalPos.y;
set_actor_anim(ACTOR_PLAYER, 0, ANIM_Mario1_SpinFall);
return ApiStatus_DONE1;
}
break;
case SUPER_STATE_21:
temp_f20 = playerState->curPos.x;
temp_f20 += (playerState->bounceDivisor * sin_rad(DEG_TO_RAD(playerState->unk_24))) / 33.0;
playerState->curPos.x = temp_f20;
playerState->curPos.y -= playerState->bounceDivisor * sin_rad(DEG_TO_RAD(playerState->unk_24));
playerState->unk_24 += playerState->unk_28;
playerState->unk_24 = clamp_angle(playerState->unk_24);
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y;
player->curPos.z = playerState->curPos.z;
if (gBattleStatus.flags1 & BS_FLAGS1_2000) {
return ApiStatus_DONE2;
}
playerState->moveTime--;
if (playerState->moveTime == 0) {
return ApiStatus_DONE1;
}
break;
}
return ApiStatus_BLOCK;
}
API_CALLABLE(PlayerUltraJumpToGoal) {
Bytecode* args = script->ptrReadPos;
Actor* player = gBattleStatus.playerActor;
ActorState* playerState = &player->state;
f32 posX, posY, posZ;
f32 goalX, goalZ;
f32 speed;
f32 temp;
f64 temp_f20;
f64 temp_f20_2;
f64 temp_f20_4;
f64 temp_f20_5;
f64 temp_f20_6;
f64 temp_f20_7;
f64 temp_f22;
f64 temp_f22_2;
f64 temp_f22_3;
f64 temp_f22_4;
f64 temp_f22_5;
f64 temp_f22_6;
f64 temp_f22_7;
enum {
ULTRA_STATE_00 = 0,
ULTRA_STATE_01 = 1,
ULTRA_STATE_10 = 10,
ULTRA_STATE_11 = 11,
ULTRA_STATE_20 = 20,
ULTRA_STATE_21 = 21,
ULTRA_STATE_30 = 30,
ULTRA_STATE_31 = 31,
};
if (isInitialCall) {
player->state.moveTime = evt_get_variable(script, *args++);
player->state.moveArcAmplitude = evt_get_variable(script, *args++);
script->functionTemp[1] = 0;
script->functionTemp[0] = ULTRA_STATE_00;
if (player->state.moveArcAmplitude == PLAYER_ULTRA_JUMP_1) {
script->functionTemp[0] = ULTRA_STATE_11;
}
if (player->state.moveArcAmplitude == PLAYER_ULTRA_JUMP_3) {
script->functionTemp[0] = ULTRA_STATE_20;
}
if (player->state.moveArcAmplitude == PLAYER_ULTRA_JUMP_2 || player->state.moveArcAmplitude == PLAYER_ULTRA_JUMP_4) {
script->functionTemp[0] = ULTRA_STATE_30;
}
}
switch (script->functionTemp[0]) {
case ULTRA_STATE_00:
playerState->curPos.x = player->curPos.x;
playerState->curPos.y = player->curPos.y;
playerState->curPos.z = player->curPos.z;
goalX = playerState->goalPos.x;
goalZ = playerState->goalPos.z;
posX = playerState->curPos.x;
posY = playerState->curPos.y;
posZ = playerState->curPos.z;
playerState->angle = atan2(posX, posZ, goalX, goalZ);
playerState->dist = dist2D(posX, posZ, goalX, goalZ);
if (playerState->moveTime == 0) {
playerState->moveTime = playerState->dist / playerState->speed;
temp = playerState->dist - (playerState->moveTime * playerState->speed);
} else {
playerState->speed = playerState->dist / playerState->moveTime;
temp = playerState->dist - (playerState->moveTime * playerState->speed);
}
playerState->acceleration = PI_S / playerState->moveTime;
playerState->vel = 0.0f;
playerState->velStep.x = (playerState->goalPos.x - playerState->curPos.x) / playerState->moveTime;
playerState->velStep.y = (playerState->goalPos.y - playerState->curPos.y) / playerState->moveTime;
playerState->velStep.z = (playerState->goalPos.z - playerState->curPos.z) / playerState->moveTime;
playerState->speed += temp / playerState->moveTime;
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpFall);
sfx_play_sound_at_position(SOUND_LONG_PLAYER_JUMP, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
sfx_play_sound_at_position(SOUND_TORNADO_JUMP, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
playerState->unk_18.x = 0.0f;
playerState->unk_18.y = 0.0f;
playerState->unk_24 = 90.0f;
temp = playerState->dist;
temp -= 20.0;
temp /= 6.0;
temp += 47.0;
playerState->bounceDivisor = temp;
temp_f20 = playerState->vel;
temp_f22 = playerState->acceleration;
playerState->unk_28 = 360 / playerState->moveTime;
playerState->vel = temp_f20 + (((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53) * temp_f22) + temp_f22);
script->functionTemp[0] = ULTRA_STATE_01;
break;
case ULTRA_STATE_10:
playerState->curPos.x = player->curPos.x;
playerState->curPos.y = player->curPos.y;
playerState->curPos.z = player->curPos.z;
goalX = playerState->goalPos.x;
goalZ = playerState->goalPos.z;
posX = playerState->curPos.x;
posY = playerState->curPos.y;
posZ = playerState->curPos.z;
playerState->angle = atan2(posX, posZ, goalX, goalZ);
playerState->dist = dist2D(posX, posZ, goalX, goalZ);
if (playerState->moveTime == 0) {
playerState->moveTime = playerState->dist / playerState->speed;
temp = playerState->dist - (playerState->moveTime * playerState->speed);
} else {
speed = playerState->dist / playerState->moveTime;
playerState->speed = speed;
temp = playerState->dist - (playerState->moveTime * speed);
}
playerState->acceleration = PI_S / playerState->moveTime;
playerState->vel = 0.0f;
playerState->velStep.x = (playerState->goalPos.x - playerState->curPos.x) / playerState->moveTime;
playerState->velStep.y = (playerState->goalPos.y - playerState->curPos.y) / playerState->moveTime;
playerState->velStep.z = (playerState->goalPos.z - playerState->curPos.z) / playerState->moveTime;
playerState->speed += temp / playerState->moveTime;
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpRise);
sfx_play_sound_at_position(SOUND_LONG_PLAYER_JUMP, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
sfx_play_sound_at_position(SOUND_TORNADO_JUMP, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
playerState->unk_18.x = 0.0f;
playerState->unk_18.y = 0.0f;
playerState->unk_24 = 90.0f;
temp_f20_2 = playerState->vel;
temp_f22_2 = playerState->acceleration;
temp = playerState->dist;
temp -= 20.0;
temp /= 6.0;
temp += 47.0;
playerState->bounceDivisor = temp;
playerState->unk_28 = 360 / playerState->moveTime;
playerState->vel = temp_f20_2 + (((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53) * temp_f22_2) + temp_f22_2);
script->functionTemp[0] = ULTRA_STATE_11;
break;
case ULTRA_STATE_20:
playerState->moveTime = 1;
set_actor_anim(ACTOR_PLAYER, 1, ANIM_Mario1_SpinFall);
player->rot.y = 0.0f;
playerState->unk_24 = 90.0f;
playerState->bounceDivisor = fabsf(playerState->unk_18.x - playerState->unk_18.y) / 16.5;
playerState->unk_28 = 360 / playerState->moveTime;
playerState->curPos.x = player->curPos.x;
playerState->curPos.y = player->curPos.y;
playerState->curPos.z = player->curPos.z;
script->functionTemp[0] = ULTRA_STATE_21;
break;
case ULTRA_STATE_30:
playerState->curPos.x = player->curPos.x;
playerState->curPos.y = player->curPos.y;
playerState->curPos.z = player->curPos.z;
goalX = playerState->goalPos.x;
goalZ = playerState->goalPos.z;
posX = playerState->curPos.x;
posY = playerState->curPos.y;
posZ = playerState->curPos.z;
playerState->angle = atan2(posX, posZ, goalX, goalZ);
playerState->dist = dist2D(posX, posZ, goalX, goalZ);
if (playerState->moveTime == 0) {
playerState->moveTime = playerState->dist / playerState->speed;
temp = playerState->dist - (playerState->moveTime * playerState->speed);
} else {
playerState->speed = playerState->dist / playerState->moveTime;
temp = playerState->dist - (playerState->moveTime * playerState->speed);
}
playerState->acceleration = PI_S / (playerState->moveTime + 1);
playerState->vel = 0.0f;
playerState->velStep.x = (playerState->goalPos.x - playerState->curPos.x) / playerState->moveTime;
playerState->velStep.y = (playerState->goalPos.y - playerState->curPos.y) / playerState->moveTime;
playerState->velStep.z = (playerState->goalPos.z - playerState->curPos.z) / playerState->moveTime;
playerState->speed += temp / playerState->moveTime;
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpRise);
sfx_play_sound_at_position(SOUND_LONG_PLAYER_JUMP, SOUND_SPACE_DEFAULT, player->curPos.x, player->curPos.y, player->curPos.z);
playerState->unk_24 = 90.0f;
playerState->bounceDivisor = 45.0f;
playerState->unk_28 = 360 / playerState->moveTime;
if (playerState->moveArcAmplitude == 4) {
playerState->bounceDivisor = 56.25f;
}
playerState->unk_18.x = 0.0f;
playerState->unk_18.y = 0.0f;
temp_f22_3 = playerState->acceleration;
temp_f22_7 = playerState->vel;
temp_f22_7 = temp_f22_7 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53 * temp_f22_3) + temp_f22_3);
playerState->vel = temp_f22_7;
script->functionTemp[0] = ULTRA_STATE_31;
break;
}
switch (script->functionTemp[0]) {
case ULTRA_STATE_01:
temp_f22_4 = playerState->vel;
temp_f20_4 = playerState->acceleration;
playerState->vel = temp_f22_4 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53 * temp_f20_4) + temp_f20_4);
playerState->curPos.x += playerState->velStep.x;
playerState->curPos.y += playerState->velStep.y;
playerState->curPos.z += playerState->velStep.z;
playerState->unk_18.x = player->curPos.y;
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y + (playerState->bounceDivisor * sin_rad(playerState->vel));
player->curPos.z = playerState->curPos.z;
playerState->unk_18.y = player->curPos.y;
playerState->unk_24 += playerState->unk_28;
playerState->unk_24 = clamp_angle(playerState->unk_24);
player->rot.y += 133.0f;
player->rot.y = clamp_angle(player->rot.y);
if (gBattleStatus.flags1 & BS_FLAGS1_2000) {
return ApiStatus_DONE2;
}
playerState->moveTime--;
if (playerState->moveTime == 4) {
return ApiStatus_DONE1;
}
break;
case ULTRA_STATE_11:
temp_f22_6 = playerState->vel;
temp_f20_7 = playerState->acceleration;
playerState->vel = temp_f22_6 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53 * temp_f20_7) + temp_f20_7);
playerState->curPos.x += playerState->velStep.x;
playerState->curPos.y += playerState->velStep.y;
playerState->curPos.z += playerState->velStep.z;
playerState->unk_18.x = player->curPos.y;
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y + (playerState->bounceDivisor * sin_rad(playerState->vel));
player->curPos.z = playerState->curPos.z;
if (playerState->goalPos.y > player->curPos.y && playerState->moveTime < 3) {
player->curPos.y = playerState->goalPos.y;
}
playerState->unk_18.y = player->curPos.y;
playerState->unk_24 += playerState->unk_28;
playerState->unk_24 = clamp_angle(playerState->unk_24);
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpFall);
player->rot.y += 133.0f;
player->rot.y = clamp_angle(player->rot.y);
playerState->moveTime--;
if (playerState->moveTime == 0) {
playerState->acceleration = 1.8f;
playerState->vel = -(playerState->unk_18.x - playerState->unk_18.y);
player->curPos.y = playerState->goalPos.y;
player->rot.y = 0.0f;
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpLand);
play_movement_dust_effects(2, player->curPos.x, player->curPos.y, player->curPos.z, player->yaw);
return ApiStatus_DONE1;
}
break;
case ULTRA_STATE_21:
temp_f20_5 = playerState->curPos.x;
temp_f20_5 += (playerState->bounceDivisor * sin_rad(DEG_TO_RAD(playerState->unk_24))) / 33.0;
playerState->curPos.x = temp_f20_5;
playerState->curPos.y -= playerState->bounceDivisor * sin_rad(DEG_TO_RAD(playerState->unk_24));
playerState->unk_24 += playerState->unk_28;
playerState->unk_24 = clamp_angle(playerState->unk_24);
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y;
player->curPos.z = playerState->curPos.z;
if (gBattleStatus.flags1 & BS_FLAGS1_2000) {
return ApiStatus_DONE2;
}
playerState->moveTime--;
if (playerState->moveTime == 0) {
return ApiStatus_DONE1;
}
break;
case ULTRA_STATE_31:
temp_f22_5 = playerState->vel;
temp_f20_6 = playerState->acceleration;
playerState->vel = temp_f22_5 + ((sin_rad(DEG_TO_RAD(playerState->unk_24)) * 0.53 * temp_f20_6) + temp_f20_6);
playerState->curPos.x += playerState->velStep.x;
playerState->curPos.y += playerState->velStep.y;
playerState->curPos.z += playerState->velStep.z;
playerState->unk_18.x = player->curPos.y;
player->curPos.x = playerState->curPos.x;
player->curPos.y = playerState->curPos.y + (playerState->bounceDivisor * sin_rad(playerState->vel));
player->curPos.z = playerState->curPos.z;
if (playerState->goalPos.y > player->curPos.y && playerState->moveTime < 3) {
player->curPos.y = playerState->goalPos.y;
}
playerState->unk_18.y = player->curPos.y;
playerState->unk_24 += playerState->unk_28;
playerState->unk_24 = clamp_angle(playerState->unk_24);
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpFall);
player->rot.y += 133.0f;
player->rot.y = clamp_angle(player->rot.y);
playerState->moveTime--;
if (playerState->moveTime == 0) {
player->curPos.y = playerState->goalPos.y;
player->rot.y = 0.0f;
set_actor_anim(ACTOR_PLAYER, 0, playerState->animJumpLand);
playerState->acceleration = 1.8f;
playerState->vel = -(playerState->unk_18.x - playerState->unk_18.y);
return ApiStatus_DONE1;
}
break;
}
return ApiStatus_BLOCK;
}
API_CALLABLE(GetPlayerActionQuality) {
Bytecode* args = script->ptrReadPos;
s32 outVar = *args++;
s32 actionQuality = gBattleStatus.actionQuality;
s32 quality = 0;
if (actionQuality < 0) {
actionQuality = 0;
}
if (quality < actionQuality) {
quality = actionQuality;
}
evt_set_variable(script, outVar, quality);
return ApiStatus_DONE2;
}
API_CALLABLE(PlayerYieldTurn) {
gBattleStatus.flags1 |= BS_FLAGS1_YIELD_TURN;
return ApiStatus_DONE2;
}
API_CALLABLE(DispatchEventPlayer) {
dispatch_event_player(evt_get_variable(script, *script->ptrReadPos));
return ApiStatus_DONE2;
}