727 lines
22 KiB
C
727 lines
22 KiB
C
#include "target.h"
|
|
|
|
#include <sys/types.h>
|
|
#include <libgte.h>
|
|
#include <libgpu.h>
|
|
|
|
#include "common.h"
|
|
#include "libgv/libgv.h"
|
|
#include "game.h"
|
|
#include "linkvar.h"
|
|
|
|
// Instead of dynamically allocating TARGETs,
|
|
// the game uses the big TARGET array gTargets_800B64E0.
|
|
//
|
|
// This also makes it easier to iterate over all TARGETs in use.
|
|
//
|
|
// Therefore each entry in this array will be either:
|
|
// - already used up (returned by GM_AllocTarget and not yet freed)
|
|
// - not used (target->class == 0)
|
|
//
|
|
// When allocating new TARGETs, the game will try to find a "free" slot in this array.
|
|
// It tries to do it efficiently (without having to scan the whole array too often).
|
|
// The game tries to ensure that slots [0, gTargets_lastSlotUsed_800ABA68)
|
|
// are all actively used, while the latter part of the array is free.
|
|
// However, deallocating TARGETs can result in "holes" in that contiguous prefix.
|
|
//
|
|
// Two indicies are maintained:
|
|
// - gTargets_lastSlotUsed_800ABA68:
|
|
// slots [0, gTargets_lastSlotUsed_800ABA68) are potentially used
|
|
// slots [gTargets_lastSlotUsed_800ABA68, TARGET_ARRAY_LENGTH) are definitely not used
|
|
// - gTargets_orphanedSlots_800ABA6C:
|
|
// how many slots [0, gTargets_lastSlotUsed_800ABA68) are not used
|
|
//
|
|
// In most cases the game will just take gTargets_lastSlotUsed_800ABA68+1
|
|
// as a next used slot. If a TARGET is freed in the middle of the array
|
|
// (gets orphaned: gTargets_orphanedSlots_800ABA6C) the code will try
|
|
// to "plug" the hole when allocating the next target.
|
|
//
|
|
// Example:
|
|
// - [Target1, Target2, Target3, FREE, FREE, FREE, FREE...]
|
|
// gTargets_lastSlotUsed_800ABA68 = 3, gTargets_orphanedSlots_800ABA6C = 0
|
|
//
|
|
// - GM_AllocTarget()
|
|
//
|
|
// - [Target1, Target2, Target3, Target4, FREE, FREE, FREE...]
|
|
// gTargets_lastSlotUsed_800ABA68 = 4, gTargets_orphanedSlots_800ABA6C = 0
|
|
//
|
|
// - GM_FreeTarget(Target3)
|
|
//
|
|
// - [Target1, Target2, FREE, Target4, FREE, FREE, FREE...]
|
|
// gTargets_lastSlotUsed_800ABA68 = 4, gTargets_orphanedSlots_800ABA6C = 1
|
|
//
|
|
// - GM_AllocTarget()
|
|
//
|
|
// - [Target1, Target2, Target5, Target4, FREE, FREE, FREE...]
|
|
// gTargets_lastSlotUsed_800ABA68 = 4, gTargets_orphanedSlots_800ABA6C = 0
|
|
//
|
|
// - GM_FreeTarget(Target4)
|
|
//
|
|
// - [Target1, Target2, Target5, FREE, FREE, FREE, FREE...]
|
|
// gTargets_lastSlotUsed_800ABA68 = 3, gTargets_orphanedSlots_800ABA6C = 0
|
|
//
|
|
extern TARGET gTargets_800B64E0[TARGET_ARRAY_LENGTH];
|
|
|
|
STATIC int SECTION(".sbss") gTargets_lastSlotUsed_800ABA68;
|
|
STATIC int SECTION(".sbss") gTargets_orphanedSlots_800ABA6C;
|
|
|
|
static inline int BoundContains(int asize, int bsize, int apos, int bpos)
|
|
{
|
|
int size;
|
|
|
|
size = asize + bsize;
|
|
return ( bpos >= ( apos - size ) ) && ( apos >= ( bpos - size ) );
|
|
}
|
|
|
|
static inline int MapContains(int a, int b)
|
|
{
|
|
return (GM_PlayerMap & a) && (GM_PlayerMap & b);
|
|
}
|
|
|
|
// Checks if two targets intersect.
|
|
// For an intersection, the two targets must be:
|
|
// 1. On opposing sides (PLAYER_SIDE & ENEMY_SIDE)
|
|
// 2. Contained within one's bounds
|
|
// 3. On the same map(s)
|
|
int GM_TargetIntersects(TARGET *a, TARGET *b)
|
|
{
|
|
return (((a->side & b->side) == 0) &&
|
|
BoundContains(a->size.vx, b->size.vx, a->center.vx, b->center.vx) &&
|
|
BoundContains(a->size.vz, b->size.vz, a->center.vz, b->center.vz) &&
|
|
BoundContains(a->size.vy, b->size.vy, a->center.vy, b->center.vy) &&
|
|
MapContains(a->map, b->map));
|
|
}
|
|
|
|
// Checks if a target with no side intersects with a given target.
|
|
// Similar to GM_TargetIntersects, but `a` must be on NO_SIDE.
|
|
int GM_TargetIntersectsNoSide(TARGET *a, TARGET *b)
|
|
{
|
|
return (a->side == NO_SIDE &&
|
|
BoundContains(a->size.vx, b->size.vx, a->center.vx, b->center.vx) &&
|
|
BoundContains(a->size.vz, b->size.vz, a->center.vz, b->center.vz) &&
|
|
BoundContains(a->size.vy, b->size.vy, a->center.vy, b->center.vy) &&
|
|
MapContains(a->map, b->map));
|
|
}
|
|
|
|
void GM_ResetTargets(void)
|
|
{
|
|
gTargets_lastSlotUsed_800ABA68 = 0;
|
|
gTargets_orphanedSlots_800ABA6C = 0;
|
|
}
|
|
|
|
TARGET *GM_AllocTarget(void)
|
|
{
|
|
TARGET *target;
|
|
int i;
|
|
|
|
// The game tries to maintain that slots [0, gTargets_lastSlotUsed_800ABA68)
|
|
// in gTargets_800B64E0 are all used up. However some "holes" could appear.
|
|
|
|
// Are there no "holes" to plug in the gTargets_800B64E0 array?
|
|
if (gTargets_orphanedSlots_800ABA6C == 0)
|
|
{
|
|
// There are no "holes" in the gTargets_800B64E0 array
|
|
// so let's just take the next slot and increment gTargets_lastSlotUsed_800ABA68
|
|
|
|
if (gTargets_lastSlotUsed_800ABA68 >= TARGET_ARRAY_LENGTH)
|
|
{
|
|
// Out of memory...
|
|
return NULL;
|
|
}
|
|
|
|
target = &gTargets_800B64E0[gTargets_lastSlotUsed_800ABA68];
|
|
target->class = TARGET_AVAIL;
|
|
gTargets_lastSlotUsed_800ABA68++;
|
|
return target;
|
|
}
|
|
|
|
// There are "holes" in the gTargets_800B64E0 array, let's
|
|
// try to find one and use it up.
|
|
|
|
target = gTargets_800B64E0;
|
|
if (gTargets_lastSlotUsed_800ABA68 > 0)
|
|
{
|
|
for (i = gTargets_lastSlotUsed_800ABA68; i > 0; i--, target++)
|
|
{
|
|
if (target->class == TARGET_STALE)
|
|
{
|
|
// Found unused slot, let's use it.
|
|
target->class = TARGET_AVAIL;
|
|
gTargets_orphanedSlots_800ABA6C--;
|
|
return target;
|
|
}
|
|
}
|
|
}
|
|
|
|
// This should be unreachable, we should have found a slot above.
|
|
gTargets_orphanedSlots_800ABA6C = 0;
|
|
return NULL;
|
|
}
|
|
|
|
void GM_FreeTarget(TARGET *target)
|
|
{
|
|
// The game tries to maintain that slots [0, gTargets_lastSlotUsed_800ABA68)
|
|
// in gTargets_800B64E0 are all used up. However some "holes" could appear
|
|
// due to freeing a TARGET here:
|
|
|
|
if (target)
|
|
{
|
|
if (target == &gTargets_800B64E0[gTargets_lastSlotUsed_800ABA68 - 1])
|
|
{
|
|
// Freeing the last used TARGET doesn't result
|
|
// in a "hole", just adjust the lastSlotUsed.
|
|
gTargets_lastSlotUsed_800ABA68--;
|
|
}
|
|
else
|
|
{
|
|
// Freeing this TARGET resulted in a "hole" in the array:
|
|
gTargets_orphanedSlots_800ABA6C++;
|
|
}
|
|
target->class = TARGET_STALE; // mark as a free slot
|
|
}
|
|
}
|
|
|
|
void GM_MoveTarget(TARGET *target, SVECTOR *center)
|
|
{
|
|
target->center = *center;
|
|
target->map = GM_CurrentMap;
|
|
}
|
|
|
|
TARGET *GM_CaptureTarget(TARGET *target)
|
|
{
|
|
TARGET *iter;
|
|
int i;
|
|
|
|
iter = gTargets_800B64E0;
|
|
for (i = gTargets_lastSlotUsed_800ABA68; i > 0; iter++, i--)
|
|
{
|
|
// Skip if we are checking the current target
|
|
if (target == iter)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Skip if wrong class
|
|
if (!(iter->class & TARGET_CAPTURE))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Return if this is the first intersection for the class
|
|
if (GM_TargetIntersects(iter, target) && !(iter->damaged & TARGET_CAPTURE))
|
|
{
|
|
iter->damaged |= TARGET_CAPTURE;
|
|
iter->a_mode = target->a_mode;
|
|
iter->field_18 = target->field_18;
|
|
iter->field_1C = target->field_1C;
|
|
iter->faint -= target->faint;
|
|
iter->captured = 1;
|
|
|
|
target->damaged |= TARGET_CAPTURE;
|
|
|
|
return iter;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
TARGET *GM_C4Target(TARGET *target)
|
|
{
|
|
TARGET *iter;
|
|
int i;
|
|
|
|
iter = gTargets_800B64E0;
|
|
for (i = gTargets_lastSlotUsed_800ABA68; i > 0; iter++, i--)
|
|
{
|
|
// Skip if we are checking the current target
|
|
if (target == iter)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Skip if wrong class
|
|
if (!(iter->class & TARGET_C4))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Return if this is the first intersection for the class
|
|
if (GM_TargetIntersects(iter, target) && !(iter->damaged & TARGET_C4))
|
|
{
|
|
iter->damaged |= TARGET_C4;
|
|
target->damaged |= TARGET_C4;
|
|
return iter;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int GM_TouchTarget(TARGET *target)
|
|
{
|
|
TARGET *iter;
|
|
int i;
|
|
int hp, oldhp;
|
|
|
|
if (!(target->class & TARGET_TOUCH))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (target->damaged & TARGET_TOUCH)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
iter = gTargets_800B64E0;
|
|
i = gTargets_lastSlotUsed_800ABA68;
|
|
|
|
hp = target->life;
|
|
|
|
iter = gTargets_800B64E0;
|
|
for (i = gTargets_lastSlotUsed_800ABA68; i > 0; iter++, i--)
|
|
{
|
|
// Skip if we are checking the current target
|
|
if (target == iter)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Skip if wrong class
|
|
if (!(iter->class & TARGET_TOUCH))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Touch if there is an intersection for the class
|
|
if (GM_TargetIntersects(iter, target))
|
|
{
|
|
oldhp = iter->life;
|
|
iter->life -= hp;
|
|
iter->life_lost += oldhp - iter->life;
|
|
|
|
iter->damaged |= TARGET_TOUCH;
|
|
target->damaged |= TARGET_TOUCH;
|
|
}
|
|
}
|
|
|
|
// Return whether any target was touched
|
|
return (target->damaged & TARGET_TOUCH) >> 7;
|
|
}
|
|
|
|
static inline int sub_helper_8002D7DC(int mode, int a, int b)
|
|
{
|
|
switch (mode & 0x3)
|
|
{
|
|
case 0:
|
|
return 0;
|
|
|
|
case 1:
|
|
return a - b;
|
|
|
|
case 2:
|
|
return (a > b) ? a : 0;
|
|
|
|
default:
|
|
return a;
|
|
}
|
|
}
|
|
|
|
#define SCALE_VXZ(in, scale, out) \
|
|
do \
|
|
{ \
|
|
int angle; \
|
|
angle = GV_VecDir2(in); \
|
|
GV_DirVec2(angle, scale, out); \
|
|
} while (0)
|
|
|
|
int GM_PowerTarget(TARGET *target)
|
|
{
|
|
SVECTOR dist;
|
|
SVECTOR scaled;
|
|
int hp, hp2;
|
|
int p_mode;
|
|
TARGET *iter;
|
|
int i;
|
|
int hp_diff;
|
|
|
|
hp = target->life;
|
|
p_mode = target->p_mode;
|
|
|
|
iter = gTargets_800B64E0;
|
|
for (i = gTargets_lastSlotUsed_800ABA68; i > 0; iter++, i--)
|
|
{
|
|
if (target == iter)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!(iter->class & TARGET_POWER))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!GM_TargetIntersects(iter, target))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
iter->damaged |= TARGET_POWER;
|
|
|
|
hp2 = iter->life;
|
|
iter->life = sub_helper_8002D7DC(iter->p_mode, hp2, hp);
|
|
hp = sub_helper_8002D7DC(p_mode, hp, hp2);
|
|
|
|
iter->life_lost += hp2 - iter->life;
|
|
iter->faint -= target->faint;
|
|
iter->a_mode = target->a_mode;
|
|
iter->weapon = target->weapon;
|
|
|
|
if (p_mode & 0x4)
|
|
{
|
|
GV_SubVec3(&iter->center, &target->center, &dist);
|
|
SCALE_VXZ(&dist, target->scale.vx, &scaled);
|
|
GV_AddVec3(&iter->scale, &scaled, &iter->scale);
|
|
}
|
|
else
|
|
{
|
|
GV_AddVec3(&iter->scale, &target->scale, &iter->scale);
|
|
}
|
|
|
|
if (hp < 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
hp_diff = target->life - hp;
|
|
target->life = hp;
|
|
|
|
if (hp_diff > 0)
|
|
{
|
|
target->damaged |= TARGET_POWER;
|
|
}
|
|
|
|
return hp_diff;
|
|
}
|
|
|
|
static inline int sub_helper2_8002DA14( TARGET *target, TARGET *target2, int use_z )
|
|
{
|
|
int a, b;
|
|
int v0, v1;
|
|
|
|
b = use_z ? target2->size.vz : target2->size.vx;
|
|
a = use_z ? target->size.vz : target->size.vx;
|
|
|
|
v1 = use_z ? target2->center.vz : target2->center.vx;
|
|
v0 = use_z ? target->center.vz : target->center.vx;
|
|
|
|
b = b + a;
|
|
a = v0 - v1;
|
|
|
|
|
|
if (a >= 0)
|
|
{
|
|
b -= a;
|
|
if (b < 0)
|
|
{
|
|
b = 0;
|
|
}
|
|
return b;
|
|
}
|
|
else
|
|
{
|
|
a += b;
|
|
if (a < 0)
|
|
{
|
|
a = 0;
|
|
}
|
|
return -a;
|
|
}
|
|
}
|
|
|
|
static inline int sub_helper_8002DA14(TARGET *target, TARGET *iter)
|
|
{
|
|
int val, val2;
|
|
int which;
|
|
|
|
val = sub_helper2_8002DA14(target, iter, 0);
|
|
if (val == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
val2 = sub_helper2_8002DA14(target, iter, 1);
|
|
if (val2 == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (!(iter->field_3C & 2))
|
|
{
|
|
// this is NOT an inline, /= 2 does not work otherwise
|
|
if (abs(val) <= abs(val2))
|
|
{
|
|
val /= 2;
|
|
target->offset.vx += val;
|
|
iter->offset.vx -= val;
|
|
|
|
if (val > 0)
|
|
{
|
|
which = 2;
|
|
}
|
|
else
|
|
{
|
|
which = 4;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
val2 /= 2;
|
|
target->offset.vz += val2;
|
|
iter->offset.vz -= val2;
|
|
|
|
if (val2 > 0)
|
|
{
|
|
which = 1;
|
|
}
|
|
else
|
|
{
|
|
which = 3;
|
|
}
|
|
}
|
|
|
|
if (iter->field_3C & 1)
|
|
{
|
|
target->offset.pad = which;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int GM_PushTarget(TARGET *target)
|
|
{
|
|
TARGET *iter;
|
|
int count;
|
|
|
|
if (!(target->class & TARGET_PUSH))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
target->offset = DG_ZeroVector;
|
|
target->offset.pad = 0;
|
|
|
|
iter = gTargets_800B64E0;
|
|
|
|
for (count = gTargets_lastSlotUsed_800ABA68; count > 0; iter++, count--)
|
|
{
|
|
iter->push_side = NO_SIDE;
|
|
|
|
if ((target == iter) || !(iter->class & TARGET_PUSH) || !GM_TargetIntersectsNoSide(iter, target))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (sub_helper_8002DA14(target, iter))
|
|
{
|
|
iter->damaged |= TARGET_PUSH;
|
|
target->damaged |= TARGET_PUSH;
|
|
iter->push_side = target->side;
|
|
}
|
|
}
|
|
|
|
return (short)(target->damaged & TARGET_PUSH) > 0;
|
|
}
|
|
|
|
void GM_SetTarget(TARGET *target, int class, int side, SVECTOR *size)
|
|
{
|
|
short cur_map = GM_CurrentMap;
|
|
target->class = class;
|
|
target->side = side;
|
|
target->damaged = 0;
|
|
target->map = cur_map;
|
|
target->size = *size;
|
|
target->field_3C = 0;
|
|
}
|
|
|
|
void GM_Target_8002DCB4(TARGET *target, int a_mode, int faint, int *a4, SVECTOR *a5)
|
|
{
|
|
target->field_18 = a4;
|
|
target->a_mode = a_mode;
|
|
target->faint = faint;
|
|
target->field_1C = a5;
|
|
}
|
|
|
|
void GM_Target_8002DCCC(TARGET *target, int p_mode, int a_mode, int life, int faint, SVECTOR *scale)
|
|
{
|
|
target->p_mode = p_mode;
|
|
target->a_mode = a_mode;
|
|
target->life = life;
|
|
target->life_lost = 0;
|
|
target->faint = faint;
|
|
target->scale = *scale;
|
|
target->weapon = WP_None;
|
|
}
|
|
|
|
void GM_TargetBody(TARGET *target, MATRIX *body)
|
|
{
|
|
target->body = body;
|
|
}
|
|
|
|
void sub_8002DD1C(SVECTOR *svec1, SVECTOR *svec2, TARGET *target)
|
|
{
|
|
int coord1, coord2;
|
|
int diff;
|
|
|
|
coord1 = svec1->vx;
|
|
coord2 = svec2->vx;
|
|
diff = (coord1 - coord2) / 2;
|
|
target->center.vx = (coord1 + coord2) / 2;
|
|
target->size.vx = abs(diff);
|
|
|
|
coord1 = svec1->vy;
|
|
coord2 = svec2->vy;
|
|
diff = (coord1 - coord2) / 2;
|
|
target->center.vy = (coord1 + coord2) / 2;
|
|
target->size.vy = abs(diff);
|
|
|
|
coord1 = svec1->vz;
|
|
coord2 = svec2->vz;
|
|
diff = (coord1 - coord2) / 2;
|
|
target->center.vz = (coord1 + coord2) / 2;
|
|
target->size.vz = abs(diff);
|
|
}
|
|
|
|
#define sub_8002DDE0_helper(AXIS1, AXIS2, AXIS3) \
|
|
{ \
|
|
int vec1_axis1, vec1_axis2, vec1_axis3; \
|
|
int outvec_axis1, outvec_axis3; \
|
|
int outvec_addend_axis2; \
|
|
int multiplier; \
|
|
int target_field_10_axis1; \
|
|
vec1_axis1 = vec1->AXIS1; \
|
|
divisor = vec2->AXIS1 - vec1_axis1; \
|
|
if (divisor != 0) \
|
|
{ \
|
|
outvec_axis1 = target->center.AXIS1; \
|
|
target_field_10_axis1 = target->size.AXIS1; \
|
|
if (target->center.AXIS1 < vec1_axis1) \
|
|
{ \
|
|
outvec_axis1 += target_field_10_axis1; \
|
|
if (vec1_axis1 < outvec_axis1) \
|
|
{ \
|
|
outvec_axis1 = vec1_axis1; \
|
|
} \
|
|
} \
|
|
else \
|
|
{ \
|
|
outvec_axis1 -= target_field_10_axis1; \
|
|
if (outvec_axis1 < vec1_axis1) \
|
|
{ \
|
|
outvec_axis1 = vec1_axis1; \
|
|
} \
|
|
} \
|
|
multiplier = outvec_axis1 - vec1_axis1; \
|
|
vec1_axis2 = vec1->AXIS2; \
|
|
outvec_addend_axis2 = (vec2->AXIS2 - vec1_axis2) * multiplier / divisor; \
|
|
if (vec1_axis2 + outvec_addend_axis2 >= target->center.AXIS2 - target->size.AXIS2 && \
|
|
target->center.AXIS2 + target->size.AXIS2 >= vec1_axis2 + outvec_addend_axis2) \
|
|
{ \
|
|
vec1_axis3 = vec1->AXIS3; \
|
|
outvec_axis3 = vec1_axis3; \
|
|
outvec_axis3 += (vec2->AXIS3 - outvec_axis3) * multiplier / divisor; \
|
|
if (outvec_axis3 >= target->center.AXIS3 - target->size.AXIS3 && \
|
|
target->center.AXIS3 + target->size.AXIS3 >= outvec_axis3) \
|
|
{ \
|
|
do \
|
|
{ \
|
|
outvec->AXIS1 = outvec_axis1; \
|
|
outvec->AXIS2 = vec1_axis2 + outvec_addend_axis2; \
|
|
outvec->AXIS3 = outvec_axis3; \
|
|
} while (0); \
|
|
return 1; \
|
|
} \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
int sub_8002DDE0(SVECTOR *vec1, SVECTOR *vec2, TARGET *target, SVECTOR *outvec)
|
|
{
|
|
int divisor;
|
|
sub_8002DDE0_helper(vx, vy, vz);
|
|
sub_8002DDE0_helper(vy, vz, vx);
|
|
sub_8002DDE0_helper(vz, vx, vy);
|
|
return 0;
|
|
}
|
|
|
|
int GM_Target_8002E1B8(SVECTOR *pVec, SVECTOR *pVec1, int map_bit, SVECTOR *pVec2, int side)
|
|
{
|
|
TARGET *iter;
|
|
int i;
|
|
int bResult;
|
|
TARGET target;
|
|
|
|
target.map = map_bit;
|
|
target.side = NO_SIDE;
|
|
sub_8002DD1C(pVec, pVec1, &target);
|
|
|
|
iter = gTargets_800B64E0;
|
|
i = gTargets_lastSlotUsed_800ABA68;
|
|
for (bResult = 0; i > 0; ++iter)
|
|
{
|
|
if (iter->side != side && (iter->class & TARGET_SEEK) != 0)
|
|
{
|
|
if (GM_TargetIntersects(iter, &target))
|
|
{
|
|
if (sub_8002DDE0(pVec, pVec1, iter, pVec2))
|
|
{
|
|
sub_8002DD1C(pVec, pVec2, &target);
|
|
bResult = 1;
|
|
}
|
|
}
|
|
}
|
|
--i;
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
int sub_8002E2A8(SVECTOR *arg0, SVECTOR *arg1, int map, SVECTOR *arg3)
|
|
{
|
|
TARGET target;
|
|
TARGET *iter;
|
|
int count;
|
|
|
|
target.map = map;
|
|
target.side = NO_SIDE;
|
|
|
|
sub_8002DD1C(arg0, arg1, &target);
|
|
|
|
iter = gTargets_800B64E0;
|
|
count = gTargets_lastSlotUsed_800ABA68;
|
|
|
|
while (count > 0)
|
|
{
|
|
if (((iter->field_3C & 0x1) != 0) &&
|
|
((iter->class & TARGET_SEEK) != 0) &&
|
|
GM_TargetIntersects(iter, &target) &&
|
|
sub_8002DDE0(arg0, arg1, iter, arg3))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
iter++;
|
|
count--;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void GM_Target_8002E374(int *ppDownCount, TARGET **targets)
|
|
{
|
|
*ppDownCount = gTargets_lastSlotUsed_800ABA68;
|
|
*targets = gTargets_800B64E0;
|
|
}
|