mirror of https://github.com/zeldaret/tmc.git
FireballChain OK, start documenting
This commit is contained in:
parent
946bb8095b
commit
13e7c6a5ee
|
@ -0,0 +1,12 @@
|
|||
#ifndef PROJECTILE_WINDER_H
|
||||
#define PROJECTILE_WINDER_H
|
||||
#include "enemy.h"
|
||||
|
||||
#define WINDER_NUM_SEGMENTS 8
|
||||
|
||||
typedef struct {
|
||||
Entity base;
|
||||
s16 positions[2 * WINDER_NUM_SEGMENTS];
|
||||
} WinderEntity;
|
||||
|
||||
#endif
|
|
@ -787,7 +787,7 @@ SECTIONS {
|
|||
src/object/objectA2.o(.text);
|
||||
src/object/cloud.o(.text);
|
||||
src/object/minishLight.o(.text);
|
||||
asm/object/fireballChain.o(.text);
|
||||
src/object/fireballChain.o(.text);
|
||||
src/object/objectA6.o(.text);
|
||||
src/object/objectA7.o(.text);
|
||||
src/object/objectA8.o(.text);
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#define NENT_DEPRECATED
|
||||
#include "global.h"
|
||||
#include "entity.h"
|
||||
#include "functions.h"
|
||||
#include "projectile.h"
|
||||
#include "projectile/winder.h"
|
||||
|
||||
void FireballChain(Entity* thisx) {
|
||||
WinderEntity* newSegment;
|
||||
Entity* parent;
|
||||
Entity* child;
|
||||
s32 i;
|
||||
s32 j;
|
||||
|
||||
if (gEntCount > 0x42) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
u16* tmp;
|
||||
|
||||
newSegment = (WinderEntity*)CreateProjectile(WINDER);
|
||||
if (i == 0) {
|
||||
child = parent = &newSegment->base;
|
||||
}
|
||||
|
||||
newSegment->base.type = i;
|
||||
newSegment->base.parent = parent;
|
||||
newSegment->base.child = child;
|
||||
CopyPosition(thisx, &newSegment->base);
|
||||
|
||||
for (j = 0, tmp = newSegment->positions; j < WINDER_NUM_SEGMENTS; j++) {
|
||||
*tmp++ = thisx->x.HALF.HI;
|
||||
*tmp++ = thisx->y.HALF.HI;
|
||||
}
|
||||
|
||||
child = &newSegment->base;
|
||||
}
|
||||
|
||||
DeleteThisEntity();
|
||||
}
|
|
@ -1,118 +1,139 @@
|
|||
#define NENT_DEPRECATED
|
||||
#include "entity.h"
|
||||
#include "asm.h"
|
||||
#include "functions.h"
|
||||
#include "common.h"
|
||||
#include "projectile.h"
|
||||
#include "projectile/winder.h"
|
||||
|
||||
// #define WINDER_NUM_SEGMENTS 8
|
||||
|
||||
extern void (*const Winder_Actions[])(Entity*);
|
||||
extern s16 gUnk_080B4488[];
|
||||
static const u8 gUnk_0812A6BC[];
|
||||
static const u16 gUnk_0812A6C4[];
|
||||
|
||||
void sub_080AB9DC(Entity*);
|
||||
bool32 sub_080AB9FC(Entity* this, u32 param_1);
|
||||
// typedef struct {
|
||||
// Entity base;
|
||||
// u16 positions[2 * WINDER_NUM_SEGMENTS];
|
||||
// } WinderEntity;
|
||||
|
||||
void Winder(Entity* this) {
|
||||
Winder_Actions[this->action](this);
|
||||
sub_080AB9DC(this);
|
||||
typedef enum {
|
||||
/* 0 */ WINDER_TYPE_HEAD,
|
||||
/* 4 */ WINDER_TYPE_4 = 4,
|
||||
} WinderType;
|
||||
|
||||
void Winder_Init(WinderEntity* this);
|
||||
void sub_080AB950(WinderEntity* this);
|
||||
|
||||
void Winder_SetPositions(WinderEntity*);
|
||||
bool32 sub_080AB9FC(WinderEntity* this, u32 dir);
|
||||
|
||||
void Winder(Entity* thisx) {
|
||||
static void (*const Winder_Actions[])(WinderEntity*) = {
|
||||
Winder_Init,
|
||||
sub_080AB950,
|
||||
};
|
||||
WinderEntity* this = (WinderEntity*)thisx;
|
||||
|
||||
Winder_Actions[super->action](this);
|
||||
Winder_SetPositions(this);
|
||||
}
|
||||
|
||||
void Winder_Init(Entity* this) {
|
||||
Entity* entity;
|
||||
u16* puVar3;
|
||||
s32 index;
|
||||
void Winder_Init(WinderEntity* this) {
|
||||
Entity* nextSegment;
|
||||
u16* posPtr;
|
||||
s32 i;
|
||||
|
||||
this->action += 1;
|
||||
this->speed = 0x140;
|
||||
this->z.WORD = 0;
|
||||
if (this->type == 0) {
|
||||
this->direction = Random() & 0x18;
|
||||
this->parent = this;
|
||||
super->action++;
|
||||
super->speed = 0x140;
|
||||
super->z.WORD = 0;
|
||||
if (super->type == 0) {
|
||||
super->direction = Random() & 0x18;
|
||||
super->parent = super;
|
||||
}
|
||||
InitializeAnimation(this, 0);
|
||||
if (this->type < 4) {
|
||||
entity = CreateProjectile(WINDER);
|
||||
entity->type = this->type + 1;
|
||||
entity->parent = this->parent;
|
||||
entity->child = this;
|
||||
CopyPosition(this, entity);
|
||||
InitializeAnimation(super, 0);
|
||||
if (super->type < 4) {
|
||||
nextSegment = CreateProjectile(WINDER);
|
||||
nextSegment->type = super->type + 1;
|
||||
nextSegment->parent = super->parent;
|
||||
nextSegment->child = super;
|
||||
CopyPosition(super, nextSegment);
|
||||
}
|
||||
|
||||
puVar3 = &this->field_0x68.HWORD;
|
||||
for (index = 7; index >= 0; --index) {
|
||||
*puVar3 = this->x.HALF.HI;
|
||||
puVar3 += 1;
|
||||
*puVar3 = this->y.HALF.HI;
|
||||
puVar3 += 1;
|
||||
posPtr = this->positions;
|
||||
for (i = 0; i < WINDER_NUM_SEGMENTS; i++) {
|
||||
*posPtr++ = super->x.HALF.HI;
|
||||
*posPtr++ = super->y.HALF.HI;
|
||||
}
|
||||
}
|
||||
|
||||
void sub_080AB950(Entity* this) {
|
||||
if (this->type == 0) {
|
||||
void sub_080AB950(WinderEntity* this) {
|
||||
static const u8 nextDirections[][2] = {
|
||||
{ DirectionEast, DirectionWest },
|
||||
{ DirectionNorth, DirectionSouth },
|
||||
{ DirectionEast, DirectionWest },
|
||||
{ DirectionNorth, DirectionSouth },
|
||||
};
|
||||
static const u16 gUnk_0812A6C4[] = { 0x000E, 0xE000, 0x00E0, 0x0E00 };
|
||||
|
||||
if (super->type == 0) {
|
||||
u8 dir;
|
||||
ProcessMovement0(this);
|
||||
dir = this->direction >> 3;
|
||||
if (((gUnk_0812A6C4)[dir] & this->collisions) || sub_080AB9FC(this, this->direction)) {
|
||||
this->direction = gUnk_0812A6BC[(Random() & 0x1) + (dir << 1)];
|
||||
|
||||
ProcessMovement0(super);
|
||||
|
||||
dir = super->direction >> 3;
|
||||
if ((gUnk_0812A6C4[dir] & super->collisions) || sub_080AB9FC(this, super->direction)) {
|
||||
super->direction = nextDirections[dir][Random() & 0x1];
|
||||
}
|
||||
} else {
|
||||
Entity* child;
|
||||
WinderEntity* child;
|
||||
|
||||
if (this->parent == NULL) {
|
||||
if (super->parent == NULL) {
|
||||
DeleteThisEntity();
|
||||
}
|
||||
|
||||
if (this->parent->next == NULL) {
|
||||
if (super->parent->next == NULL) {
|
||||
DeleteThisEntity();
|
||||
}
|
||||
|
||||
child = this->child;
|
||||
if (child && child->next) {
|
||||
this->x.HALF.HI = child->field_0x68.HWORD;
|
||||
this->y.HALF.HI = child->field_0x6a.HWORD;
|
||||
child = (WinderEntity*)super->child;
|
||||
if ((child != NULL) && (child->base.next != NULL)) {
|
||||
super->x.HALF.HI = child->positions[0];
|
||||
super->y.HALF.HI = child->positions[1];
|
||||
} else {
|
||||
DeleteThisEntity();
|
||||
}
|
||||
}
|
||||
|
||||
GetNextFrame(this);
|
||||
GetNextFrame(super);
|
||||
}
|
||||
|
||||
void sub_080AB9DC(Entity* this) {
|
||||
MemCopy(&this->field_0x6c, &this->field_0x68, 0x1c);
|
||||
this->cutsceneBeh.HWORD = this->x.HALF.HI;
|
||||
this->field_0x86.HWORD = this->y.HALF.HI;
|
||||
void Winder_SetPositions(WinderEntity* this) {
|
||||
//! @bug Undefined behaviour for source and destination to overlap in a memcpy. In this case it is okay because the
|
||||
//! copy will always be sequential, incremental and in chunks of <= 4 bytes, so it will copy the contents of
|
||||
//! positions[0] and positions[1] to positions[2] and positions[3], then that of positions[2] and positions[3] to
|
||||
//! positions[4] and positions[5], and so on. A safer way to do this would be a manual loop as in sub_080AB950.
|
||||
MemCopy(&this->positions[2], &this->positions[0], sizeof(u16) * (ARRAY_COUNT(this->positions) - 2));
|
||||
|
||||
this->positions[2 * (WINDER_NUM_SEGMENTS - 1)] = super->x.HALF.HI;
|
||||
this->positions[2 * (WINDER_NUM_SEGMENTS - 1) + 1] = super->y.HALF.HI;
|
||||
}
|
||||
|
||||
bool32 sub_080AB9FC(Entity* this, u32 dir) {
|
||||
bool32 sub_080AB9FC(WinderEntity* this, u32 dir) {
|
||||
u32 val;
|
||||
LayerStruct* layer = GetLayerByIndex(this->collisionLayer);
|
||||
LayerStruct* layer = GetLayerByIndex(super->collisionLayer);
|
||||
u32 tmp;
|
||||
val = (((this->x.HALF.HI - gRoomControls.origin_x) >> 4) & 0x3f) |
|
||||
((((this->y.HALF.HI - gRoomControls.origin_y) >> 4) & 0x3f) << 6);
|
||||
|
||||
val = (((super->x.HALF.HI - gRoomControls.origin_x) >> 4) & 0x3F) |
|
||||
((((super->y.HALF.HI - gRoomControls.origin_y) >> 4) & 0x3F) << 6);
|
||||
val += gUnk_080B4488[dir >> 3];
|
||||
tmp = layer->collisionData[val];
|
||||
if (tmp <= 0x1f) {
|
||||
return 0;
|
||||
|
||||
if (tmp <= 0x1F) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (tmp > 0x3f) {
|
||||
return 0;
|
||||
if (tmp > 0x3F) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void (*const Winder_Actions[])(Entity*) = {
|
||||
Winder_Init,
|
||||
sub_080AB950,
|
||||
};
|
||||
const u8 gUnk_0812A6BC[] = {
|
||||
8, 24, 0, 16, 8, 24, 0, 16,
|
||||
};
|
||||
const u16 gUnk_0812A6C4[] = {
|
||||
0xe,
|
||||
0xe000,
|
||||
0xe0,
|
||||
0xe00,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue