summaryrefslogtreecommitdiff
path: root/src/projectile/arrowProjectile.c
blob: eeba0cf08c3d981b4c5c0942cfed70f1a961d1ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/**
 * @file arrowProjectile.c
 * @ingroup Projectiles
 *
 * @brief Arrow Projectile
 */
#include "collision.h"
#include "enemy.h"
#include "sound.h"
#include "effects.h"
#include "projectile.h"
#include "entity.h"
#include "object.h"
#include "asm.h"
#include "physics.h"
#include "player.h"

extern void (*const ArrowProjectile_Functions[])(Entity*);
extern void (*const ArrowProjectile_Actions[])(Entity*);

typedef struct {
    u8 flipX;
    u8 flipY;
    u8 animIndex;
    u8 unk;
    const Hitbox* hitbox;
} struct_081299F8;
extern const struct_081299F8 gUnk_081299F8[];

void sub_080A9488(Entity*);
void sub_080A94C0(Entity*, u32);

void ArrowProjectile(Entity* this) {
    ArrowProjectile_Functions[GetNextFunction(this)](this);
}

void ArrowProjectile_OnTick(Entity* this) {
    ArrowProjectile_Actions[this->action](this);
}

void ArrowProjectile_OnCollision(Entity* this) {
    if ((this->contactFlags & CONTACT_NOW) != 0) {
        if ((this->contactFlags & 0x3f) != 0) {
            ModHealth(-2);
            sub_080A9488(this);
            this->knockbackDuration = 0;
            this->iframes = 0;
        } else {
            DeleteThisEntity();
        }
    }
}

void ArrowProjectile_Init(Entity* this) {
    this->action = 1;
    this->spriteSettings.draw = 1;
    COLLISION_OFF(this);
    this->timer = 106;
    this->subtimer = 0;
    this->zVelocity = Q_16_16(10.0 / 256.0);
    sub_080A94C0(this, this->type);
}

void ArrowProjectile_Action1(Entity* this) {
    Entity* parent = this->parent;
    if ((parent == NULL) || (parent->next == NULL)) {
        DeleteThisEntity();
    }
    if (this->subtimer != 0) {
        DeleteThisEntity();
    }
    if (parent->subtimer != 0) {
        this->action = 2;
        COLLISION_ON(this);
        parent->child = NULL;
        SoundReq(SFX_FC);
    }
}

void ArrowProjectile_Action2(Entity* this) {
    if (this->collisions != COL_NONE) {
        this->action = 3;
        COLLISION_OFF(this);
        this->timer = 32;
        InitializeAnimation(this, this->animIndex + 2);
        EnqueueSFX(SFX_18A);
        LinearMoveUpdate(this);
    } else if (--this->timer == 0) {
        DeleteThisEntity();
    }
    ProcessMovement3(this);
}

void ArrowProjectile_Action3(Entity* this) {
    if (--this->timer == 0) {
        DeleteThisEntity();
    }
    GetNextFrame(this);
}

void ArrowProjectile_Action4(Entity* this) {
    if (GravityUpdate(this, Q_8_8(40.0)) == 0) {
        CreateDeathFx(this);
        DeleteThisEntity();
    } else {
        if (--this->timer == 0) {
            this->timer = 2;
            this->animationState = (this->animationState + 1) & 3;
            sub_080A94C0(this, this->animationState);
        }
    }
}

void sub_080A9488(Entity* this) {
    this->action = 4;
    COLLISION_OFF(this);
    this->timer = 2;
    this->zVelocity = Q_16_16(1.5);
    this->animationState = (this->knockbackDirection & 0x18) >> 3;
    EnqueueSFX(SFX_METAL_CLINK);
    sub_080A94C0(this, this->animationState);
}

void sub_080A94C0(Entity* this, u32 animationState) {
    const struct_081299F8* entry = &gUnk_081299F8[animationState];
    this->spriteSettings.flipX = entry->flipX;
    this->spriteSettings.flipY = entry->flipY;
    this->animIndex = entry->animIndex;
    this->hitbox = (Hitbox*)entry->hitbox;
    InitializeAnimation(this, this->animIndex);
}

void (*const ArrowProjectile_Functions[])(Entity*) = {
    ArrowProjectile_OnTick, ArrowProjectile_OnCollision, DeleteEntity, DeleteEntity, DeleteEntity,
};
void (*const ArrowProjectile_Actions[])(Entity*) = {
    ArrowProjectile_Init,    ArrowProjectile_Action1, ArrowProjectile_Action2,
    ArrowProjectile_Action3, ArrowProjectile_Action4,
};

extern const Hitbox gUnk_08129A18;
extern const Hitbox gUnk_08129A20;

const struct_081299F8 gUnk_081299F8[] = {
    { 0, 0, 1, 0, &gUnk_08129A20 },
    { 1, 0, 0, 0, &gUnk_08129A18 },
    { 0, 1, 1, 0, &gUnk_08129A20 },
    { 0, 0, 0, 0, &gUnk_08129A18 },
};

const Hitbox gUnk_08129A18 = { 0, 0, { 4, 0, 0, 0 }, 6, 4 };
const Hitbox gUnk_08129A20 = { 0, 0, { 0, 0, 0, 4 }, 4, 6 };