/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at
golgotha_source@usa.net (Subject should have "GOLG" in it)
***********************************************************************/
#include "g1_object.hh"
#include "objs/model_draw.hh"
#include "math/num_type.hh"
#include "objs/rocket.hh"
#include "tile.hh"
#include "objs/explosion1.hh"
#include "saver.hh"
#include "objs/fire_angle.hh"
#include "math/pi.hh"
#include "objs/map_piece.hh"
#include "map.hh"
#include "map_man.hh"
#include "math/angle.hh"
#include "math/trig.hh"
#include "image/image.hh"
#include "objs/smoke_trail.hh"
#include "object_definer.hh"
#include "g1_render.hh"
#include "g1_rand.hh"
static g1_object_type shrapnel_type, explosion_type, smoke_trail_type;
void g1_rocket_init()
{
shrapnel_type = g1_get_object_type("shrapnel");
explosion_type = g1_get_object_type("explosion1");
smoke_trail_type = g1_get_object_type("smoke_trail");
}
g1_object_definer
g1_rocket_def("rocket",
g1_object_definition_class::MOVABLE,
g1_rocket_init);
g1_rocket_class::g1_rocket_class(g1_object_type id,
g1_loader_class *fp)
: g1_object_class(id,fp)
{
draw_params.setup("missile");
if (fp && fp->check_version(G1_ROCKET_DATA_VERSION))
{
zv=fp->read_float();
speed=fp->read_float();
fp->read_reference(who_fired_me);
fp->read_reference(track_object);
i4_warning("loaded rocket that does no damage");
fp->end_version(I4_LF);
}
else
{
zv=0;
speed=0;
}
damage = 0;
radar_type=G1_RADAR_WEAPON;
set_flag(AERIAL |
HIT_GROUND |
SHADOWED, 1);
}
void g1_rocket_class::save(g1_saver_class *fp)
{
// save data associated with base classes
g1_object_class::save(fp);
fp->start_version(G1_ROCKET_DATA_VERSION);
fp->write_float(zv);
fp->write_float(speed);
fp->write_reference(who_fired_me);
fp->write_reference(track_object);
fp->end_version();
}
void g1_rocket_class::fire_at(i4_float sx, i4_float sy, i4_float sz,
i4_float angle,
g1_map_piece_class *kill_target,
g1_map_piece_class *owner,
w32 _damage)
{
damage = _damage;
lx=x=sx; ly=y=sy; lh=h=sz;
i4_float x_y_dist = sqrt((kill_target->x - sx)*(kill_target->x - sx) +
(kill_target->y - sy)*(kill_target->y - sy));
i4_float angle_with_ground;
if (!g1_calc_fire_angle(x_y_dist, sz, kill_target->h, g(), vo(), angle_with_ground))
angle_with_ground=i4_pi()/4;
speed=cos(angle_with_ground)*vo();
zv=sin(angle_with_ground)*vo();
ltheta=theta=angle;
pitch = lpitch = atan(-zv/speed);
player_num=owner->player_num;
track_object = kill_target;
who_fired_me = owner;
occupy_location();
request_think();
}
void g1_rocket_class::fire(i4_float sx, i4_float sy, i4_float sz,
i4_angle angle,
g1_map_piece_class *owner,
w32 _damage)
{
damage = _damage;
i4_float angle_with_ground=i4_pi()/4;
speed=cos(angle_with_ground)*vo();
zv=sin(angle_with_ground)*vo();
theta=angle;
who_fired_me = owner;
player_num=owner->player_num;
occupy_location();
request_think();
}
void i4_normalize_angle(i4_float &angle);
void g1_rocket_class::think()
{
zv-=g();
pitch = atan(-zv/speed);
i4_normalize_angle(pitch);
move(cos(theta) * speed, sin(theta) * speed, zv);
}
void g1_rocket_class::draw(g1_draw_context_class *context)
{
g1_model_draw(this, draw_params, context);
if (smoke_trail.valid())
smoke_trail->draw(context);
}
i4_bool g1_rocket_class::move(i4_float x_amount,
i4_float y_amount,
i4_float z_amount)
{
g1_smoke_trail_class *s;
if (!smoke_trail.valid())
{
s=(g1_smoke_trail_class *)g1_create_object(smoke_trail_type);
if (s)
{
s->setup(x, y, h, 0.01, 0.1, 0xffd000, 0xffffff); // orange to white
s->occupy_location();
smoke_trail=s;
}
}
else s=(g1_smoke_trail_class *)smoke_trail.get();
g1_object_class *hit = NULL;
unoccupy_location();
i4_3d_vector ray(x_amount, y_amount, z_amount);
if (!g1_get_map()->check_non_player_collision(player_num,
i4_3d_vector(x,y,h),
ray,
hit))
{
x += x_amount;
y += y_amount;
h += z_amount;
request_think();
occupy_location();
if (s)
s->update_head(x,y,h);
return i4_T;
}
else
{
if (s) // delete the smoke trail
{
s->unoccupy_location();
s->request_remove();
}
// explode
if (hit)
{
if (fabs(hit->h - h)<0.2)
{
hit->damage(this, damage, i4_3d_vector(x_amount,y_amount,z_amount));
g1_explosion1_class *explosion;
explosion=(g1_explosion1_class *)g1_create_object(explosion_type);
i4_float rx,ry,rh;
rx = g1_float_rand(34) *0.2 - 0.1;
ry = g1_float_rand(10) *0.2 - 0.1;
rh = g1_float_rand(02) *0.2 - 0.1;
explosion->setup(hit->x+rx,hit->y+ry,hit->h + rh);
x = hit->x + rx;
y = hit->y + ry;
h = hit->h + rh;
request_remove();
return i4_F;;
}
x += x_amount;
y += y_amount;
h += z_amount;
request_think();
occupy_location();
return i4_T;
}
else if (who_fired_me.valid())
{
g1_explosion1_class *explosion=(g1_explosion1_class *)g1_create_object(explosion_type);
i4_float rx,ry,rh;
rx = g1_float_rand(34) *0.2 - 0.1;
ry = g1_float_rand(10) *0.2 - 0.1;
rh = g1_float_rand(02) *0.2 - 0.1;
explosion->setup(lx+rx,ly+ry,lh+rh);
}
request_remove();
return i4_F;
}
}