/**********************************************************************
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 "saver.hh"
#include "objs/model_draw.hh"
#include "objs/model_collide.hh"
#include "map.hh"
#include "map_man.hh"
#include "objs/shrapnel.hh"
#include "math/random.hh"
#include "objs/miscobjs.hh"
class g1_deco_definition_class;
g1_deco_type_manager_class g1_deco_type_manager;
static g1_object_type shrapnel_type=0;
g1_deco_object_class::g1_deco_object_class(g1_object_type id, g1_loader_class *fp)
: g1_object_class(id, fp), death(this)
{
model_name=0;
health=100;
if (fp)
{
w16 ver,data_size;
fp->get_version(ver,data_size);
switch (ver)
{
case 2 :
health=fp->read_16();
case 1 :
char buf[1024];
int len=fp->read_16();
fp->read(buf, len);
model_name=g1_deco_type_manager.find_name(buf);
if (model_name)
{
char lod_name[256];
sprintf(lod_name, "%s_lod", model_name);
draw_params.setup(model_name, 0, lod_name);
}
}
fp->end_version(I4_LF);
}
collision_type = 1;
player_num=G1_MAX_PLAYERS-1;
set_flag(BLOCKING |
SELECTABLE |
CAN_DRIVE_ON |
TARGETABLE |
GROUND |
SHADOWED,
1);
}
void g1_deco_object_class::save(g1_saver_class *fp)
{
g1_object_class::save(fp);
fp->start_version(DATA_VERSION);
fp->write_16(health);
if (model_name)
{
int len=strlen(model_name)+1;
fp->write_16(len);
fp->write((void*)model_name, len);
}
else fp->write_16(0);
fp->end_version();
}
i4_bool g1_deco_object_class::check_collision(const i4_3d_vector &start, i4_3d_vector &ray)
{
i4_3d_vector normal;
switch (collision_type)
{
case 0: return g1_model_collide_radial(this, draw_params, start, ray);
case 1: return g1_model_collide_polygonal(this, draw_params, start, ray, normal);
default: return i4_F;
}
i4_error("case not handled");
return i4_F;
}
void g1_deco_object_class::think()
{
if (occupancy_radius()>0.8 && !death.think())
return;
if (model_name==0)
{
unoccupy_location();
request_remove();
}
if (health<0)
{
g1_shrapnel_class *shrapnel = NULL;
if (!shrapnel_type)
shrapnel_type = g1_get_object_type("shrapnel");
shrapnel = (g1_shrapnel_class *)g1_create_object(shrapnel_type);
if (shrapnel)
{
i4_float rh = (i4_rand()&0xFFFF)/((i4_float)0xFFFF) * 0.2;
shrapnel->setup(x, y, h + rh, 10, i4_T);
}
unoccupy_location();
request_remove();
}
}
void g1_deco_object_class::damage(g1_object_class *who_is_hurting,
int how_much_hurt, i4_3d_vector damage_dir)
{
if (occupancy_radius()>0.8)
death.damage(who_is_hurting, how_much_hurt, damage_dir);
else
g1_object_class::damage(who_is_hurting,how_much_hurt,damage_dir);
}
class g1_deco_definition_class : public g1_object_definition_class
{
public:
char deco_name[40];
g1_object_class *create_object(g1_object_type type,
g1_loader_class *fp)
{
g1_deco_object_class *o=new g1_deco_object_class(type, fp);
if (!fp)
{
o->model_name=_name;
if (o->model_name)
{
char lod_name[256];
sprintf(lod_name, "%s_lod", o->model_name);
o->draw_params.setup(o->model_name, 0, lod_name);
o->set_flag(g1_object_class::SHADOWED,1);
}
}
o->init();
return o;
}
g1_deco_definition_class(char *__name)
: g1_object_definition_class(strcpy(deco_name, __name))
{
set_flag(MOVABLE,0);
}
~g1_deco_definition_class()
{
g1_deco_type_manager.remove_type(this);
}
};
g1_object_type g1_create_deco_object(char *name)
{
g1_deco_definition_class *def=new g1_deco_definition_class(name);
g1_object_type t=def->type;
def->flags|=g1_object_definition_class::TO_DECO_OBJECT |
g1_object_definition_class::DELETE_WITH_LEVEL;
g1_deco_type_manager.add_type(def);
return t;
}
const char *g1_deco_type_manager_class::find_name(const char *name)
{
for (int i=0; iname())==0)
return deco_objs[i]->name();
}
return 0; // this object name doesn't exsist in the game anymore
}
void g1_deco_type_manager_class::uninit()
{
deco_objs.uninit();
}