MuckyFoot-UrbanChaos/fallen/Source/lead.cpp
2017-05-20 11:14:17 +10:00

265 lines
3.9 KiB
C++

#include "game.h"
#include "pap.h"
#include "lead.h"
#include "animate.h"
#include "ob.h"
//
// The structures.
//
LEAD_Lead LEAD_lead[LEAD_MAX_LEADS];
SLONG LEAD_lead_upto;
LEAD_Point LEAD_point[LEAD_MAX_POINTS];
SLONG LEAD_point_upto;
void LEAD_init()
{
memset(LEAD_lead, 0, sizeof(LEAD_lead));
memset(LEAD_point, 0, sizeof(LEAD_point));
LEAD_lead_upto = 1;
LEAD_point_upto = 1;
}
void LEAD_create(
SLONG len,
SLONG world_x,
SLONG world_y,
SLONG world_z)
{
SLONG p_num;
LEAD_Lead *ll;
//
// How many points do we need?
//
switch(len)
{
case LEAD_LEN_SHORT: p_num = 8; break;
case LEAD_LEN_MEDIUM: p_num = 16; break;
case LEAD_LEN_LONG: p_num = 32; break;
default:
ASSERT(0);
break;
}
//
// Do we have enough points?
//
if (LEAD_point_upto + p_num > LEAD_MAX_POINTS)
{
return;
}
//
// Ran out of objects?
//
if (LEAD_lead_upto >= LEAD_MAX_LEADS)
{
return;
}
ll = &LEAD_lead[LEAD_lead_upto];
ll->p_num = p_num;
ll->p_index = LEAD_point_upto;
ll->attach_x = world_x;
ll->attach_y = world_y;
ll->attach_z = world_z;
ll->attach_thing = NULL;
LEAD_lead_upto += 1;
LEAD_point_upto += p_num;
}
void LEAD_find_end(
UBYTE lead_index,
SLONG *end_x,
SLONG *end_y,
SLONG *end_z)
{
SLONG pos_x;
SLONG pos_y;
SLONG pos_z;
ASSERT(WITHIN(lead_index, 1, LEAD_lead_upto - 1));
LEAD_Lead *ll;
Thing *p_thing;
ll = &LEAD_lead[lead_index];
if (ll->attach_thing)
{
p_thing = TO_THING(ll->attach_thing);
switch(p_thing->Class)
{
case CLASS_PERSON:
calc_sub_objects_position(
p_thing,
p_thing->Draw.Tweened->AnimTween,
SUB_OBJECT_HEAD,
&pos_x,
&pos_y,
&pos_z);
pos_x += p_thing->WorldPos.X >> 8;
pos_y += p_thing->WorldPos.Y >> 8;
pos_z += p_thing->WorldPos.Z >> 8;
break;
case CLASS_ANIMAL:
pos_x = (p_thing->WorldPos.X >> 8);
pos_y = (p_thing->WorldPos.Y >> 8) + 0x80;
pos_z = (p_thing->WorldPos.Z >> 8);
break;
default:
ASSERT(0);
break;
}
}
else
{
//
// Pick a random to initialise the string in.
//
}
}
void LEAD_attach()
{
SLONG i;
SLONG j;
SLONG ob_x;
SLONG ob_y;
SLONG ob_z;
SLONG ob_yaw;
SLONG ob_prim;
SLONG dx;
SLONG dy;
SLONG dz;
SLONG dist;
SLONG score;
SLONG end_x;
SLONG end_y;
SLONG end_z;
SLONG best_thing = NULL;
SLONG best_score = -INFINITY;
#define LEAD_MAX_FIND 8
THING_INDEX find[LEAD_MAX_FIND];
SLONG found;
LEAD_Lead *ll;
LEAD_Point *lp;
Thing *p_found;
for (i = 1; i < LEAD_lead_upto; i++)
{
ll = &LEAD_lead[i];
//
// Look for a lampost or a tree to attach to.
//
if (OB_find_type(
ll->attach_x,
ll->attach_y,
ll->attach_z,
0x200,
PRIM_FLAG_LAMPOST | PRIM_FLAG_TREE,
&ob_x,
&ob_y,
&ob_z,
&ob_yaw,
&ob_prim))
{
ll->attach_x = ob_x;
ll->attach_y = ob_y + 0x60;
ll->attach_z = ob_z;
}
else
{
//
// We couldn't find a tree or a lampost- so just stick to the ground.
//
ll->attach_y = PAP_calc_map_height_at(ll->attach_x, ll->attach_z);
}
//
// Find an animal or person to attach to.
//
found = THING_find_sphere(
ll->attach_x,
ll->attach_y,
ll->attach_z,
0x200,
find,
LEAD_MAX_FIND,
(1 << CLASS_PERSON) | (1 << CLASS_ANIMAL));
//
// Look for the best thing to attach to.
//
for (j = 0; j < found; j++)
{
p_found = TO_THING(find[j]);
dx = (p_found->WorldPos.X >> 8) - ll->attach_x;
dy = (p_found->WorldPos.Y >> 8) - ll->attach_y;
dz = (p_found->WorldPos.Z >> 8) - ll->attach_z;
dist = QDIST3(abs(dx),abs(dy),abs(dz));
score = dist;
if (p_found->Class == CLASS_ANIMAL)
{
//
// It is better to attach to animals than to people!
//
score <<= 2;
}
if (score > best_score)
{
best_score = score;
best_thing = find[j];
}
}
ll->attach_thing = best_thing;
}
}