mirror of https://github.com/pmret/papermario.git
811 lines
30 KiB
C
811 lines
30 KiB
C
#include "common.h"
|
|
#include "battle/battle.h"
|
|
#include "script_api/battle.h"
|
|
#include "effects.h"
|
|
|
|
HitResult calc_item_check_hit(void) {
|
|
BattleStatus* battleStatus = &gBattleStatus;
|
|
ActorState* state = &battleStatus->playerActor->state;
|
|
s32 actorID = battleStatus->currentTargetID;
|
|
s8 currentTargetPartS8;
|
|
u32 currentTargetPart;
|
|
Actor* actor;
|
|
ActorPart* actorPart;
|
|
|
|
battleStatus->currentTargetID2 = battleStatus->currentTargetID;
|
|
currentTargetPart = currentTargetPartS8 = battleStatus->currentTargetPart;
|
|
battleStatus->currentTargetPart2 = currentTargetPartS8;
|
|
|
|
actor = get_actor(actorID);
|
|
if (actor == NULL) {
|
|
return HIT_RESULT_HIT;
|
|
}
|
|
|
|
actorPart = get_actor_part(actor, currentTargetPart);
|
|
ASSERT(actorPart != NULL);
|
|
|
|
if (actorPart->eventFlags & ACTOR_EVENT_FLAG_ILLUSORY) {
|
|
return HIT_RESULT_MISS;
|
|
}
|
|
|
|
if (actor->transparentStatus == STATUS_TRANSPARENT) {
|
|
return HIT_RESULT_MISS;
|
|
}
|
|
|
|
if (actor->stoneStatus == STATUS_STONE) {
|
|
sfx_play_sound_at_position(SOUND_IMMUNE, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
return HIT_RESULT_IMMUNE;
|
|
}
|
|
|
|
if ((battleStatus->currentAttackElement & DAMAGE_TYPE_JUMP)
|
|
&& (actorPart->eventFlags & ACTOR_EVENT_FLAG_SPIKY_TOP))
|
|
{
|
|
sfx_play_sound_at_position(SOUND_HIT_NORMAL, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
return HIT_RESULT_LANDED_ON_SPIKE;
|
|
}
|
|
|
|
return HIT_RESULT_HIT;
|
|
}
|
|
|
|
HitResult calc_item_damage_enemy(void) {
|
|
BattleStatus* battleStatus = &gBattleStatus;
|
|
Actor* player = battleStatus->playerActor;
|
|
s32 currentTargetID = battleStatus->currentTargetID;
|
|
Actor* partner = battleStatus->partnerActor;
|
|
s32 currentTargetPartID = battleStatus->currentTargetPart;
|
|
s32 partImmuneToElement;
|
|
s32 sp1C = FALSE;
|
|
s32 actorClass;
|
|
s32 isFireDamage = FALSE;
|
|
s32 isWaterDamage = FALSE;
|
|
s32 isShockDamage = FALSE;
|
|
s32 isIceDamage = FALSE;
|
|
Actor* target;
|
|
ActorPart* targetPart;
|
|
Evt* script;
|
|
s32 attackDamage;
|
|
s32 temp;
|
|
s32 targetDefense;
|
|
ActorState* state;
|
|
s32 dispatchEvent;
|
|
s32 wasStatusInflicted;
|
|
s32 hitResult;
|
|
|
|
battleStatus->wasStatusInflicted = FALSE;
|
|
battleStatus->lastAttackDamage = 0;
|
|
battleStatus->attackerActorID = player->actorID;
|
|
battleStatus->currentTargetID2 = battleStatus->currentTargetID;
|
|
battleStatus->currentTargetPart2 = battleStatus->currentTargetPart;
|
|
target = get_actor(currentTargetID);
|
|
wasStatusInflicted = FALSE;
|
|
|
|
if (target == NULL) {
|
|
return HIT_RESULT_HIT;
|
|
}
|
|
|
|
targetPart = get_actor_part(target, currentTargetPartID);
|
|
if (targetPart == NULL) {
|
|
PANIC();
|
|
}
|
|
|
|
target->lastDamageTaken = 0;
|
|
actorClass = currentTargetID & ACTOR_CLASS_MASK;
|
|
if (!(gBattleStatus.flags1 & BS_FLAGS1_PARTNER_ACTING)) {
|
|
state = &player->state;
|
|
} else {
|
|
state = &partner->state;
|
|
}
|
|
|
|
if (battleStatus->currentAttackElement & 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->currentAttackElement & DAMAGE_TYPE_SHOCK) {
|
|
apply_shock_effect(target);
|
|
isShockDamage = TRUE;
|
|
}
|
|
if (battleStatus->currentAttackElement & 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->currentAttackElement & DAMAGE_TYPE_ICE) {
|
|
fx_big_snowflakes(0, state->goalPos.x, state->goalPos.y, state->goalPos.z + 5.0f);
|
|
isIceDamage = TRUE;
|
|
}
|
|
|
|
if (!(battleStatus->currentAttackElement & DAMAGE_TYPE_REMOVE_BUFFS)) {
|
|
if ((targetPart->eventFlags & ACTOR_EVENT_FLAG_ILLUSORY)
|
|
|| (target->transparentStatus == STATUS_TRANSPARENT)
|
|
|| (targetPart->eventFlags & ACTOR_EVENT_FLAG_800)
|
|
&& !(battleStatus->currentAttackElement & DAMAGE_TYPE_QUAKE)
|
|
) {
|
|
return HIT_RESULT_MISS;
|
|
}
|
|
}
|
|
|
|
if (target->stoneStatus == STATUS_STONE) {
|
|
sfx_play_sound_at_position(SOUND_IMMUNE, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
func_8024EFE0(state->goalPos.x, state->goalPos.y, state->goalPos.z, 0, 1, 1);
|
|
show_damage_popup(state->goalPos.x, state->goalPos.y, state->goalPos.z, 0, 0);
|
|
if (gBattleStatus.flags1 & (BS_FLAGS1_40 | BS_FLAGS1_200)) {
|
|
return HIT_RESULT_1;
|
|
}
|
|
return HIT_RESULT_HIT;
|
|
}
|
|
|
|
if (targetPart->elementalImmunities & battleStatus->currentAttackElement) {
|
|
partImmuneToElement = TRUE;
|
|
} else {
|
|
partImmuneToElement = FALSE;
|
|
}
|
|
|
|
if (targetPart->eventFlags & (ACTOR_EVENT_FLAG_ENCHANTED | ACTOR_EVENT_FLAG_STAR_ROD_ENCHANTED)) {
|
|
battleStatus->currentAttackElement &= ~DAMAGE_TYPE_IGNORE_DEFENSE;
|
|
}
|
|
|
|
temp = get_defense(target, targetPart->defenseTable, battleStatus->currentAttackElement);
|
|
if (!(battleStatus->currentAttackElement & DAMAGE_TYPE_IGNORE_DEFENSE)) {
|
|
temp += target->defenseBoost;
|
|
}
|
|
|
|
attackDamage = battleStatus->currentAttackDamage;
|
|
if (attackDamage > 99) {
|
|
attackDamage = 99;
|
|
}
|
|
if (attackDamage <= 0) {
|
|
temp = 0;
|
|
}
|
|
|
|
attackDamage -= temp;
|
|
target->hpChangeCounter = 0;
|
|
|
|
if (attackDamage <= 0) {
|
|
target->hpChangeCounter = 0;
|
|
hitResult = HIT_RESULT_NO_DAMAGE;
|
|
|
|
if (!(battleStatus->currentAttackElement & DAMAGE_TYPE_STATUS_ALWAYS_HITS)) {
|
|
dispatchEvent = EVENT_ZERO_DAMAGE;
|
|
sfx_play_sound_at_position(SOUND_IMMUNE, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
battleStatus->lastAttackDamage = 0;
|
|
} else {
|
|
dispatchEvent = EVENT_ZERO_DAMAGE;
|
|
battleStatus->lastAttackDamage = 0;
|
|
}
|
|
} else {
|
|
target->damageCounter += attackDamage;
|
|
target->hpChangeCounter -= attackDamage;
|
|
battleStatus->lastAttackDamage = 0;
|
|
dispatchEvent = EVENT_HIT_COMBO;
|
|
hitResult = HIT_RESULT_HIT;
|
|
|
|
if (!(targetPart->flags & ACTOR_PART_FLAG_2000)
|
|
&& !partImmuneToElement
|
|
&& !(targetPart->targetFlags & ACTOR_PART_TARGET_FLAG_4)
|
|
) {
|
|
target->currentHP -= attackDamage;
|
|
if (target->currentHP <= 0) {
|
|
target->currentHP = 0;
|
|
dispatchEvent = EVENT_DEATH;
|
|
}
|
|
}
|
|
battleStatus->lastAttackDamage += attackDamage;
|
|
target->lastDamageTaken = battleStatus->lastAttackDamage;
|
|
target->hpChangeCounter = 0;
|
|
}
|
|
|
|
if (targetPart->flags & ACTOR_PART_FLAG_2000) {
|
|
dispatch_event_actor(target, dispatchEvent);
|
|
func_8024EFE0(state->goalPos.x, state->goalPos.y, state->goalPos.z, 0, 1, 3);
|
|
sfx_play_sound_at_position(SOUND_IMMUNE, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
return HIT_RESULT_NO_DAMAGE;
|
|
}
|
|
|
|
if (battleStatus->currentAttackElement & DAMAGE_TYPE_DEATH) {
|
|
battleStatus->lastAttackDamage = 0;
|
|
dispatchEvent = EVENT_DEATH;
|
|
hitResult = HIT_RESULT_HIT;
|
|
}
|
|
|
|
if (gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE) {
|
|
if (dispatchEvent == EVENT_HIT_COMBO) {
|
|
dispatchEvent = EVENT_HIT;
|
|
}
|
|
if (dispatchEvent == EVENT_ZERO_DAMAGE) {
|
|
dispatchEvent = EVENT_IMMUNE;
|
|
}
|
|
if (target->currentHP <= 0 && dispatchEvent == EVENT_IMMUNE) {
|
|
dispatchEvent = EVENT_DEATH;
|
|
}
|
|
} else if (dispatchEvent == EVENT_DEATH) {
|
|
dispatchEvent = EVENT_HIT_COMBO;
|
|
}
|
|
|
|
if (gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE) {
|
|
if (battleStatus->currentAttackElement & DAMAGE_TYPE_REMOVE_BUFFS) {
|
|
dispatchEvent = EVENT_IMMUNE;
|
|
if (targetPart->eventFlags & ACTOR_EVENT_FLAG_ENCHANTED) {
|
|
dispatchEvent = EVENT_STAR_BEAM;
|
|
wasStatusInflicted = TRUE;
|
|
}
|
|
if (targetPart->eventFlags & ACTOR_EVENT_FLAG_ATTACK_CHARGED) {
|
|
dispatchEvent = EVENT_STAR_BEAM;
|
|
wasStatusInflicted = TRUE;
|
|
}
|
|
if (targetPart->eventFlags & ACTOR_EVENT_FLAG_STAR_ROD_ENCHANTED) {
|
|
dispatchEvent = EVENT_INVUNERABLE_TAUNT;
|
|
}
|
|
hitResult = HIT_RESULT_HIT;
|
|
}
|
|
}
|
|
|
|
if (battleStatus->currentAttackElement & DAMAGE_TYPE_REMOVE_BUFFS) {
|
|
if (gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE) {
|
|
if ((target->attackBoost > 0 || target->defenseBoost > 0) ||
|
|
((target->staticStatus == 0 && target->transparentStatus != 0) || target->staticStatus != 0))
|
|
{
|
|
target->attackBoost = 0;
|
|
target->defenseBoost = 0;
|
|
target->isGlowing = FALSE;
|
|
dispatchEvent = EVENT_HIT;
|
|
if (target->staticStatus != 0) {
|
|
target->staticStatus = 0;
|
|
target->staticDuration = 0;
|
|
remove_status_static(target->hudElementDataIndex);
|
|
}
|
|
if (target->transparentStatus != 0) {
|
|
target->transparentStatus = 0;
|
|
target->transparentDuration = 0;
|
|
remove_status_transparent(target->hudElementDataIndex);
|
|
}
|
|
wasStatusInflicted = TRUE;
|
|
hitResult = HIT_RESULT_HIT;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE) {
|
|
if (battleStatus->currentAttackElement & DAMAGE_TYPE_PEACH_BEAM) {
|
|
dispatchEvent = EVENT_IMMUNE;
|
|
if (targetPart->eventFlags & ACTOR_EVENT_FLAG_ENCHANTED) {
|
|
dispatchEvent = EVENT_PEACH_BEAM;
|
|
wasStatusInflicted = TRUE;
|
|
}
|
|
if (targetPart->eventFlags & ACTOR_EVENT_FLAG_STAR_ROD_ENCHANTED) {
|
|
dispatchEvent = EVENT_PEACH_BEAM;
|
|
wasStatusInflicted = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE) {
|
|
if (battleStatus->currentAttackElement & DAMAGE_TYPE_SPIN_SMASH) {
|
|
if (dispatchEvent == EVENT_HIT) {
|
|
dispatchEvent = EVENT_SPIN_SMASH_HIT;
|
|
}
|
|
if (dispatchEvent == EVENT_DEATH) {
|
|
dispatchEvent = EVENT_SPIN_SMASH_DEATH;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE)
|
|
&& (battleStatus->currentAttackElement & (DAMAGE_TYPE_JUMP | DAMAGE_TYPE_POW))
|
|
&& (targetPart->eventFlags & ACTOR_EVENT_FLAG_GROUNDABLE)
|
|
) {
|
|
if (dispatchEvent == EVENT_HIT) {
|
|
dispatchEvent = EVENT_FALL_TRIGGER;
|
|
}
|
|
if (dispatchEvent == EVENT_IMMUNE) {
|
|
dispatchEvent = EVENT_FALL_TRIGGER;
|
|
}
|
|
}
|
|
|
|
if ((gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE)
|
|
&& (battleStatus->currentAttackElement & DAMAGE_TYPE_POW)
|
|
&& (targetPart->eventFlags & ACTOR_EVENT_FLAG_RIDING_BROOMSTICK)
|
|
) {
|
|
if (dispatchEvent == EVENT_HIT) {
|
|
dispatchEvent = EVENT_FALL_TRIGGER;
|
|
}
|
|
if (dispatchEvent == EVENT_IMMUNE) {
|
|
dispatchEvent = EVENT_FALL_TRIGGER;
|
|
}
|
|
}
|
|
|
|
if ((gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE)
|
|
&& (battleStatus->currentAttackElement & (DAMAGE_TYPE_JUMP | DAMAGE_TYPE_POW | DAMAGE_TYPE_QUAKE))
|
|
&& (targetPart->eventFlags & ACTOR_EVENT_FLAG_FLIPABLE)
|
|
) {
|
|
if (dispatchEvent == EVENT_HIT) {
|
|
dispatchEvent = EVENT_FLIP_TRIGGER;
|
|
}
|
|
if (dispatchEvent == EVENT_IMMUNE) {
|
|
dispatchEvent = EVENT_FLIP_TRIGGER;
|
|
}
|
|
}
|
|
|
|
if (gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE) {
|
|
if (battleStatus->currentAttackElement & DAMAGE_TYPE_FIRE) {
|
|
if (dispatchEvent == EVENT_HIT) {
|
|
dispatchEvent = EVENT_BURN_HIT;
|
|
}
|
|
if (dispatchEvent == EVENT_DEATH) {
|
|
dispatchEvent = EVENT_BURN_DEATH;
|
|
}
|
|
isFireDamage = TRUE;
|
|
}
|
|
}
|
|
|
|
if ((gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE)
|
|
&& battleStatus->lastAttackDamage >= 0
|
|
&& dispatchEvent != EVENT_DEATH
|
|
&& dispatchEvent != EVENT_SPIN_SMASH_DEATH
|
|
&& dispatchEvent != EVENT_EXPLODE_TRIGGER
|
|
) {
|
|
// Using this macro because it's nicer to look at, and it also is necessary to wrap the first 5 of these in a
|
|
// do-while-0 OR to wrap each one individually. It's more likely that it's a macro instead, and much cleaner
|
|
#define INFLICT_STATUS(STATUS_TYPE) \
|
|
do { \
|
|
if ((battleStatus->currentAttackStatus & STATUS_FLAG_##STATUS_TYPE) && \
|
|
try_inflict_status(target, STATUS_##STATUS_TYPE, STATUS_##STATUS_TYPE##_TURN_MOD)) { \
|
|
wasStatusInflicted = TRUE; \
|
|
} \
|
|
} while (0);
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
temp = target->actorBlueprint->spookChance;
|
|
temp = (battleStatus->statusChance * temp) / 100;
|
|
|
|
if ((gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE) && (battleStatus->currentAttackElement & DAMAGE_TYPE_FEAR)) {
|
|
if (rand_int(99) < temp
|
|
&& (target->debuff != STATUS_FEAR
|
|
&& target->debuff != STATUS_DIZZY
|
|
&& target->debuff != STATUS_PARALYZE
|
|
&& target->debuff != STATUS_SLEEP
|
|
&& target->debuff != STATUS_FROZEN
|
|
&& target->debuff != STATUS_STOP)
|
|
&& !(target->flags & ACTOR_FLAG_FLIPPED))
|
|
{
|
|
dispatchEvent = EVENT_SCARE_AWAY;
|
|
hitResult = HIT_RESULT_HIT;
|
|
sp1C = TRUE;
|
|
gBattleStatus.flags1 |= BS_FLAGS1_SP_EVT_ACTIVE | BS_FLAGS1_10 | BS_FLAGS1_8 | BS_FLAGS1_ACTORS_VISIBLE;
|
|
sfx_play_sound_at_position(SOUND_231, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
wasStatusInflicted = TRUE;
|
|
gBattleStatus.flags1 |= BS_FLAGS1_40;
|
|
} else {
|
|
dispatchEvent = EVENT_IMMUNE;
|
|
hitResult = HIT_RESULT_NO_DAMAGE;
|
|
}
|
|
}
|
|
|
|
battleStatus->wasStatusInflicted = wasStatusInflicted;
|
|
|
|
if ((sp1C
|
|
&& (gBattleStatus.flags1 & (BS_FLAGS1_40 | BS_FLAGS1_200)))
|
|
|| ((gBattleStatus.flags1 & (BS_FLAGS1_40 | BS_FLAGS1_200)) && !(gBattleStatus.flags1 & BS_FLAGS1_80))
|
|
) {
|
|
if (battleStatus->lastAttackDamage > 0) {
|
|
sfx_play_sound_at_position(SOUND_231, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
|
|
if (battleStatus->lastAttackDamage > 0 || (battleStatus->currentAttackElement & DAMAGE_TYPE_STATUS_ALWAYS_HITS) && sp1C) {
|
|
if (gBattleStatus.flags1 & BS_FLAGS1_40) {
|
|
func_802667F0(0, target, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
} else {
|
|
func_802667F0(3, target, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE) {
|
|
func_80266970(target);
|
|
}
|
|
|
|
dispatch_event_actor(target, dispatchEvent);
|
|
|
|
if (actorClass == ACTOR_PARTNER) {
|
|
if ((battleStatus->lastAttackDamage > 0) && (gBattleStatus.flags1 & BS_FLAGS1_SP_EVT_ACTIVE)) {
|
|
inflict_status(target, STATUS_DAZE, battleStatus->lastAttackDamage);
|
|
}
|
|
}
|
|
|
|
if (!(target->flags & ACTOR_FLAG_NO_DMG_POPUP)) {
|
|
if (battleStatus->lastAttackDamage == 0) {
|
|
if (!sp1C && !wasStatusInflicted) {
|
|
func_8024EFE0(state->goalPos.x, state->goalPos.y, state->goalPos.z, 0, 1, 3);
|
|
}
|
|
} else if (!partImmuneToElement) {
|
|
if (battleStatus->currentAttackElement & (DAMAGE_TYPE_SMASH | DAMAGE_TYPE_NO_OTHER_DAMAGE_POPUPS)) {
|
|
show_damage_popup(state->goalPos.x, state->goalPos.y, state->goalPos.z, battleStatus->lastAttackDamage, 0);
|
|
} else {
|
|
func_802664DC(state->goalPos.x, state->goalPos.y, state->goalPos.z, battleStatus->lastAttackDamage, 0);
|
|
}
|
|
if (!(targetPart->targetFlags & ACTOR_PART_TARGET_FLAG_4)) {
|
|
func_802666E4(target, state->goalPos.x, state->goalPos.y, state->goalPos.z, battleStatus->lastAttackDamage);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (battleStatus->lastAttackDamage > 0 && !partImmuneToElement) {
|
|
func_80267018(target, 1);
|
|
if (isFireDamage) {
|
|
sfx_play_sound_at_position(SOUND_HIT_FIRE, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
} else if (isShockDamage) {
|
|
sfx_play_sound_at_position(SOUND_HIT_SHOCK, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
} else if (isIceDamage) {
|
|
sfx_play_sound_at_position(SOUND_HIT_ICE, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
} else {
|
|
sfx_play_sound_at_position(SOUND_HIT_NORMAL, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
}
|
|
|
|
if ((battleStatus->lastAttackDamage <= 0 && !wasStatusInflicted) || (targetPart->flags & ACTOR_FLAG_2000)) {
|
|
sfx_play_sound_at_position(SOUND_IMMUNE, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
|
|
if ((battleStatus->currentAttackStatus & STATUS_FLAG_SLEEP) && wasStatusInflicted) {
|
|
script = start_script(&DoSleepHit, EVT_PRIORITY_A, 0);
|
|
script->varTable[0] = state->goalPos.x;
|
|
script->varTable[1] = state->goalPos.y;
|
|
script->varTable[2] = state->goalPos.z;
|
|
sfx_play_sound_at_position(SOUND_INFLICT_SLEEP, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
if ((battleStatus->currentAttackStatus & STATUS_FLAG_DIZZY) && wasStatusInflicted) {
|
|
script = start_script(&DoDizzyHit, EVT_PRIORITY_A, 0);
|
|
script->varTable[0] = state->goalPos.x;
|
|
script->varTable[1] = state->goalPos.y;
|
|
script->varTable[2] = state->goalPos.z;
|
|
sfx_play_sound_at_position(SOUND_INFLICT_STATUS, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
if ((battleStatus->currentAttackStatus & STATUS_FLAG_PARALYZE) && wasStatusInflicted) {
|
|
script = start_script(&DoParalyzeHit, EVT_PRIORITY_A, 0);
|
|
script->varTable[0] = state->goalPos.x;
|
|
script->varTable[1] = state->goalPos.y;
|
|
script->varTable[2] = state->goalPos.z;
|
|
sfx_play_sound_at_position(SOUND_INFLICT_STATUS, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
if ((battleStatus->currentAttackStatus & STATUS_FLAG_POISON) && wasStatusInflicted) {
|
|
script = start_script(&DoPoisonHit, EVT_PRIORITY_A, 0);
|
|
script->varTable[0] = state->goalPos.x;
|
|
script->varTable[1] = state->goalPos.y;
|
|
script->varTable[2] = state->goalPos.z;
|
|
sfx_play_sound_at_position(SOUND_INFLICT_STATUS, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
if ((battleStatus->currentAttackStatus & STATUS_FLAG_STOP) && wasStatusInflicted) {
|
|
script = start_script(&DoStopHit, EVT_PRIORITY_A, 0);
|
|
script->varTable[0] = state->goalPos.x;
|
|
script->varTable[1] = state->goalPos.y;
|
|
script->varTable[2] = state->goalPos.z;
|
|
sfx_play_sound_at_position(SOUND_INFLICT_STATUS, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
if ((battleStatus->currentAttackStatus & STATUS_FLAG_FROZEN) && wasStatusInflicted) {
|
|
script = start_script(&DoFreezeHit, EVT_PRIORITY_A, 0);
|
|
script->varTable[0] = state->goalPos.x;
|
|
script->varTable[1] = state->goalPos.y;
|
|
script->varTable[2] = state->goalPos.z;
|
|
script->varTablePtr[3] = target;
|
|
sfx_play_sound_at_position(SOUND_INFLICT_STATUS, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
if ((battleStatus->currentAttackStatus & STATUS_FLAG_SHRINK) && wasStatusInflicted) {
|
|
script = start_script(&DoShrinkHit, EVT_PRIORITY_A, 0);
|
|
script->varTable[0] = state->goalPos.x;
|
|
script->varTable[1] = state->goalPos.y;
|
|
script->varTable[2] = state->goalPos.z;
|
|
script->varTablePtr[3] = target;
|
|
sfx_play_sound_at_position(SOUND_INFLICT_STATUS, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
if ((battleStatus->currentAttackElement & DAMAGE_TYPE_SMASH) && (target->actorType == ACTOR_TYPE_GOOMNUT_TREE)) {
|
|
sfx_play_sound_at_position(SOUND_SMASH_GOOMNUT_TREE, SOUND_SPACE_MODE_0, state->goalPos.x, state->goalPos.y, state->goalPos.z);
|
|
}
|
|
|
|
func_80266ADC(target);
|
|
|
|
if (gBattleStatus.flags1 & (BS_FLAGS1_40 | BS_FLAGS1_200)) {
|
|
if (hitResult == HIT_RESULT_HIT) {
|
|
hitResult = HIT_RESULT_1;
|
|
}
|
|
if (hitResult == HIT_RESULT_NO_DAMAGE) {
|
|
hitResult = HIT_RESULT_3;
|
|
}
|
|
}
|
|
|
|
return hitResult;
|
|
}
|
|
|
|
ApiStatus ItemDamageEnemy(Evt* script, s32 isInitialCall) {
|
|
BattleStatus* battleStatus = &gBattleStatus;
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 hitResultVarOut = *args++;
|
|
s32 flags;
|
|
Actor* actor;
|
|
HitResult hitResult;
|
|
|
|
battleStatus->currentAttackElement = *args++;
|
|
battleStatus->currentAttackEventSuppression = 0;
|
|
battleStatus->currentAttackStatus = *args++;
|
|
battleStatus->currentAttackDamage = evt_get_variable(script, *args++);
|
|
flags = *args++;
|
|
|
|
if ((flags & (BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE)) == (BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE)) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else if (flags & BS_FLAGS1_10) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_10;
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else if (flags & BS_FLAGS1_SP_EVT_ACTIVE) {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_10;
|
|
gBattleStatus.flags1 |= BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_10;
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_SP_EVT_ACTIVE;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_40) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_40;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_40;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_200) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_200;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_200;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_80) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_80;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_80;
|
|
}
|
|
|
|
actor = get_actor(script->owner1.actorID);
|
|
battleStatus->currentTargetID = actor->targetActorID;
|
|
battleStatus->currentTargetPart = actor->targetPartIndex;
|
|
battleStatus->statusChance = battleStatus->currentAttackStatus;
|
|
|
|
if (battleStatus->statusChance == STATUS_CHANCE_NEVER) {
|
|
battleStatus->statusChance = 0;
|
|
}
|
|
|
|
battleStatus->statusDuration = (battleStatus->currentAttackStatus & 0xF00) >> 8;
|
|
|
|
hitResult = calc_item_damage_enemy();
|
|
if (hitResult < 0) {
|
|
return ApiStatus_FINISH;
|
|
}
|
|
|
|
evt_set_variable(script, hitResultVarOut, hitResult);
|
|
if (!does_script_exist_by_ref(script)) {
|
|
return ApiStatus_FINISH;
|
|
}
|
|
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus ItemSpookEnemy(Evt* script, s32 isInitialCall) {
|
|
BattleStatus* battleStatus = &gBattleStatus;
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 hitResultVarOut = *args++;
|
|
Actor* actor;
|
|
HitResult hitResult;
|
|
s32 flags;
|
|
|
|
battleStatus->currentAttackElement = *args++;
|
|
battleStatus->currentAttackEventSuppression = 0;
|
|
battleStatus->currentAttackStatus = *args++;
|
|
battleStatus->currentAttackStatus |= evt_get_variable(script, *args++);
|
|
battleStatus->currentAttackDamage = evt_get_variable(script, *args++);
|
|
flags = *args++;
|
|
|
|
if ((flags & (BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE)) == (BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE)) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else if (flags & BS_FLAGS1_10) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_10;
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else if (flags & BS_FLAGS1_SP_EVT_ACTIVE) {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_10;
|
|
gBattleStatus.flags1 |= BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_10;
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_SP_EVT_ACTIVE;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_40) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_40;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_40;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_200) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_200;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_200;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_80) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_80;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_80;
|
|
}
|
|
|
|
actor = get_actor(script->owner1.actorID);
|
|
battleStatus->currentTargetID = actor->targetActorID;
|
|
battleStatus->currentTargetPart = actor->targetPartIndex;
|
|
battleStatus->statusChance = battleStatus->currentAttackStatus;
|
|
|
|
if (battleStatus->statusChance == STATUS_CHANCE_NEVER) {
|
|
battleStatus->statusChance = 0;
|
|
}
|
|
|
|
battleStatus->statusDuration = (battleStatus->currentAttackStatus & 0xF00) >> 8;
|
|
|
|
hitResult = calc_item_damage_enemy();
|
|
if (hitResult < 0) {
|
|
return ApiStatus_FINISH;
|
|
}
|
|
|
|
evt_set_variable(script, hitResultVarOut, hitResult);
|
|
if (!does_script_exist_by_ref(script)) {
|
|
return ApiStatus_FINISH;
|
|
}
|
|
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus ItemAfflictEnemy(Evt* script, s32 isInitialCall) {
|
|
BattleStatus* battleStatus = &gBattleStatus;
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 hitResultVarOut = *args++;
|
|
s32 flags;
|
|
Actor* actor;
|
|
HitResult hitResult;
|
|
|
|
battleStatus->currentAttackElement = *args++;
|
|
battleStatus->currentAttackEventSuppression = 0;
|
|
battleStatus->currentAttackStatus = evt_get_variable(script, *args++);
|
|
battleStatus->currentAttackDamage = evt_get_variable(script, *args++);
|
|
flags = *args++;
|
|
|
|
if ((flags & (BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE)) == (BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE)) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else if (flags & BS_FLAGS1_10) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_10;
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else if (flags & BS_FLAGS1_SP_EVT_ACTIVE) {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_10;
|
|
gBattleStatus.flags1 |= BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_10;
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_SP_EVT_ACTIVE;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_40) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_40;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_40;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_200) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_200;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_200;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_80) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_80;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_80;
|
|
}
|
|
|
|
actor = get_actor(script->owner1.actorID);
|
|
battleStatus->currentTargetID = actor->targetActorID;
|
|
battleStatus->currentTargetPart = actor->targetPartIndex;
|
|
battleStatus->statusChance = battleStatus->currentAttackStatus;
|
|
|
|
if (battleStatus->statusChance == STATUS_CHANCE_NEVER) {
|
|
battleStatus->statusChance = 0;
|
|
}
|
|
|
|
battleStatus->statusDuration = (battleStatus->currentAttackStatus & 0xF00) >> 8;
|
|
|
|
hitResult = calc_item_damage_enemy();
|
|
if (hitResult < 0) {
|
|
return ApiStatus_FINISH;
|
|
}
|
|
|
|
evt_set_variable(script, hitResultVarOut, hitResult);
|
|
if (!does_script_exist_by_ref(script)) {
|
|
return ApiStatus_FINISH;
|
|
}
|
|
|
|
return ApiStatus_DONE2;
|
|
}
|
|
|
|
ApiStatus ItemCheckHit(Evt* script, s32 isInitialCall) {
|
|
BattleStatus* battleStatus = &gBattleStatus;
|
|
Bytecode* args = script->ptrReadPos;
|
|
s32 hitResultVarOut = *args++;
|
|
s32 flags;
|
|
Actor* actor;
|
|
HitResult hitResult;
|
|
|
|
battleStatus->currentAttackElement = *args++;
|
|
battleStatus->currentAttackEventSuppression = 0;
|
|
battleStatus->currentAttackStatus = *args++;
|
|
battleStatus->currentAttackDamage = evt_get_variable(script, *args++);
|
|
flags = *args++;
|
|
|
|
if ((flags & (BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE)) == (BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE)) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_10 | BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else if (flags & BS_FLAGS1_10) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_10;
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else if (flags & BS_FLAGS1_SP_EVT_ACTIVE) {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_10;
|
|
gBattleStatus.flags1 |= BS_FLAGS1_SP_EVT_ACTIVE;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_10;
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_SP_EVT_ACTIVE;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_40) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_40;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_40;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_200) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_200;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_200;
|
|
}
|
|
|
|
if (flags & BS_FLAGS1_80) {
|
|
gBattleStatus.flags1 |= BS_FLAGS1_80;
|
|
} else {
|
|
gBattleStatus.flags1 &= ~BS_FLAGS1_80;
|
|
}
|
|
|
|
actor = get_actor(script->owner1.actorID);
|
|
battleStatus->currentTargetID = actor->targetActorID;
|
|
battleStatus->currentTargetPart = actor->targetPartIndex;
|
|
battleStatus->statusChance = battleStatus->currentAttackStatus;
|
|
|
|
if (battleStatus->statusChance == STATUS_CHANCE_NEVER) {
|
|
battleStatus->statusChance = 0;
|
|
}
|
|
|
|
battleStatus->statusDuration = (battleStatus->currentAttackStatus & 0xF00) >> 8;
|
|
|
|
hitResult = calc_item_check_hit();
|
|
if (hitResult < 0) {
|
|
return ApiStatus_FINISH;
|
|
}
|
|
|
|
evt_set_variable(script, hitResultVarOut, hitResult);
|
|
|
|
return ApiStatus_DONE2;
|
|
}
|