/**********************************************************************
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 "object_definer.hh"
#include "lisp/li_class.hh"
#include "objs/model_draw.hh"
#include "li_objref.hh"
#include "math/random.hh"
#include "map_man.hh"
#include "map.hh"
static li_float_class_member range_when_activated("range_when_activated"),
range_when_deactivated("range_when_deactivated"),
range_when_deployed("range_when_deployed");
static li_object_class_member who_can_trigger("who_can_trigger"),
message_to_send("message_to_send"),
objects_to_trigger("objects_to_trigger"),
objects_in_range("objects_in_range"),
send_on_trigger("send_on_trigger"),
send_on_untrigger("send_on_untrigger"),
current_state("current_state"),
who_to_send("who_to_send"),
nearby_objects("nearby_objects"),
li_deploy_to("deploy_to"),
objects_to_send_next_tick("objects_to_send_next_tick");
static li_symbol_ref on("on"), off("off"), none("none"), anyone("anyone"), team("team"),
enemy("enemy");
static g1_object_type stank_type;
class g1_trigger_class : public g1_object_class
{
public:
enum trigger_type { ANYONE, TEAM_MATES, ENEMY, SUPERTANKS, ENEMY_SUPERTANKS } ;
int type;
// this matches the symbol name to our enum for faster use in C
// we leave it in symbol for in the editor easy/understandable editing
void get_trigger_type()
{
li_symbol *s=li_symbol::get(vars->get(who_can_trigger()));
char *sym[]={"anyone", "team_mates", "enemy", "supertanks", "enemy_supertanks",0 }, **a;
for (a=sym, type=0; *a && li_get_symbol(*a)!=s; a++, type++);
}
g1_trigger_class(g1_object_type id, g1_loader_class *fp)
: g1_object_class(id,fp)
{
get_trigger_type();
draw_params.setup("trigger");
}
void object_changed_by_editor(g1_object_class *who, li_class *old_vars)
{
if (who==this)
get_trigger_type();
}
// is the object in question one we should be triggered by?
i4_bool triggable_object(g1_object_class *o)
{
switch (type)
{
case ANYONE: return i4_T;
case TEAM_MATES: if (o->player_num==player_num) return i4_T;
case ENEMY: if (o->player_num!=player_num) return i4_T;
case SUPERTANKS: if (o->id==stank_type) return i4_T;
case ENEMY_SUPERTANKS: if (o->id==stank_type && o->player_num!=player_num) return i4_T;
}
}
// send our trigger message to all the object our list
void send_to_trigger_objects(li_symbol *sym)
{
if (sym==none.get()) return; // don't send none, it means "no message"
li_g1_ref_list *l=li_g1_ref_list::get(objects_to_trigger());
int t=l->size();
for (int i=0; ivalue(i);
if (o)
o->message(sym, 0,0);
}
}
// void note_enter_range(g1_object_class *who, g1_fire_range_type range)
// {
// li_class_context context(vars);
// if (range<=range_when_activated() && triggable_object(who))
// {
// li_g1_ref_list *in_range=li_g1_ref_list::get(objects_in_range());
// if (!in_range->find(who))
// {
// in_range->add(who);
// if (current_state()!=on.get())
// {
// current_state()=on.get();
// send_to_trigger_objects(li_symbol::get(send_on_trigger()));
// }
// }
// }
// }
// void note_leave_range(g1_object_class *who, g1_fire_range_type range)
// {
// li_class_context context(vars);
// if (range>=range_when_deactivated() && triggable_object(who))
// {
// li_g1_ref_list *in_range=li_g1_ref_list::get(objects_in_range());
// if (in_range->find(who))
// {
// in_range->remove(who);
// if (current_state()!=off.get())
// {
// current_state()=off.get();
// send_to_trigger_objects(li_symbol::get(send_on_untrigger()));
// }
// }
// }
// }
void think() {}
};
void g1_trigger_init()
{
stank_type=g1_get_object_type("stank");
}
static g1_object_definer
trigger_def("trigger", g1_object_definition_class::EDITOR_SELECTABLE, g1_trigger_init);
class g1_director_class : public g1_object_class
{
public:
g1_model_draw_parameters draw_params;
void draw(g1_draw_context_class *context) { g1_model_draw(this, draw_params, context); }
virtual i4_float occupancy_radius() const { return draw_params.extent(); }
g1_director_class(g1_object_type id, g1_loader_class *fp)
: g1_object_class(id,fp)
{
draw_params.setup("trigger");
}
void think()
{
li_g1_ref_list *list=li_g1_ref_list::get(objects_to_send_next_tick());
while (list->size())
{
g1_object_class *o=list->value(0);
list->remove(o->global_id);
send_object(o);
}
}
void add_to_send_list(g1_object_class *o)
{
li_g1_ref_list *list=li_g1_ref_list::get(objects_to_send_next_tick());
if (list->find(o)==-1)
list->add(o);
request_think();
}
void send_object(g1_object_class *o)
{
if (!o) return ;
li_g1_ref_list *list=li_g1_ref_list::get(li_deploy_to());
int list_size=list->size(), total=0;
// count how many valid objects we point to
for (int i=0; ivalue(i);
if (to)
total++;
}
if (total)
{
// pick one of the valid destinations
int dest=g1_rand(56)%total;
total=0;
for (int j=0; jvalue(j);
if (to)
{
if (total==dest)
{
o->deploy_to(to->x, to->y);
return ;
}
else
total++;
}
}
}
return ;
}
// void note_enter_range(g1_object_class *who, g1_fire_range_type range)
// {
// li_class_context context(vars);
// if (range<=range_when_deployed() &&
// (who_to_send()==anyone.get() ||
// (who->player_num==player_num && who_to_send()==team.get()) ||
// (who->player_num!=player_num && who_to_send()==enemy.get())))
// {
// li_g1_ref_list *r=li_g1_ref_list::get(nearby_objects());
// if (r->find(who)==-1)
// {
// r->add(who);
// add_to_send_list(who);
// }
// }
// }
// void note_leave_range(g1_object_class *who, g1_fire_range_type range)
// {
// li_class_context context(vars);
// li_g1_ref_list *r=li_g1_ref_list::get(nearby_objects());
// if (r->find(who)!=-1)
// r->remove(who);
// }
li_object *message(li_symbol *message_name, li_object *message_params, li_environment *env)
{
li_class_context context(vars);
if (message_name==on.get())
{
current_state()=on.get();
// we just turned on, see if there are any nearby object we should send
// to there destinations
li_g1_ref_list *r=li_g1_ref_list::get(nearby_objects());
int t=r->size();
for (int i=0; ivalue(i));
} else if (message_name==off.get())
current_state()=off.get();
}
// we were put down in the editor, scan for nearby objects and send them if we are on
i4_bool occupy_location()
{
li_class_context context(vars);
g1_object_class *olist[G1_MAX_OBJECTS];
int t=g1_get_map()->get_objects_in_range(x,y, range_when_deployed(), olist, G1_MAX_OBJECTS,
0xffffffff, g1_object_definition_class::MOVABLE);
li_object *o=nearby_objects();
li_g1_ref_list *r=li_g1_ref_list::get(o);
while (r->size())
r->remove(r->get_id(0));
for (int i=0; iadd(olist[i]);
if (current_state()==on.get())
add_to_send_list(olist[i]);
}
return g1_object_class::occupy_location();
}
};
static g1_object_definer
director_def("director", g1_object_definition_class::EDITOR_SELECTABLE);