source: golgotha/src/golg/objs/controllers.cc

Last change on this file was 80, checked in by Sam Hocevar, 12 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 8.6 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "object_definer.hh"
10#include "lisp/li_class.hh"
11#include "objs/model_draw.hh"
12#include "li_objref.hh"
13#include "math/random.hh"
14#include "map_man.hh"
15#include "map.hh"
16
17static li_float_class_member range_when_activated("range_when_activated"),
18  range_when_deactivated("range_when_deactivated"),
19  range_when_deployed("range_when_deployed");
20
21static li_object_class_member who_can_trigger("who_can_trigger"),
22   message_to_send("message_to_send"),
23   objects_to_trigger("objects_to_trigger"),
24   objects_in_range("objects_in_range"),
25   send_on_trigger("send_on_trigger"),
26   send_on_untrigger("send_on_untrigger"),
27   current_state("current_state"),
28   who_to_send("who_to_send"),
29   nearby_objects("nearby_objects"),
30   li_deploy_to("deploy_to"),
31   objects_to_send_next_tick("objects_to_send_next_tick");
32 
33
34static li_symbol_ref on("on"), off("off"), none("none"), anyone("anyone"), team("team"),
35  enemy("enemy");
36
37static g1_object_type stank_type;
38 
39class g1_trigger_class : public g1_object_class
40{
41public:
42  enum trigger_type { ANYONE, TEAM_MATES, ENEMY, SUPERTANKS, ENEMY_SUPERTANKS } ;
43  int type;
44 
45  // this matches the symbol name to our enum for faster use in C
46  // we leave it in symbol for in the editor easy/understandable editing
47  void get_trigger_type()
48  {   
49    li_symbol *s=li_symbol::get(vars->get(who_can_trigger()));
50    char *sym[]={"anyone", "team_mates", "enemy", "supertanks", "enemy_supertanks",0 }, **a;
51    for (a=sym, type=0; *a && li_get_symbol(*a)!=s; a++, type++);     
52  }
53 
54  g1_trigger_class(g1_object_type id, g1_loader_class *fp)
55    : g1_object_class(id,fp)
56  {
57    get_trigger_type();
58    draw_params.setup("trigger");
59  }
60
61  void object_changed_by_editor(g1_object_class *who, li_class *old_vars)
62  {
63    if (who==this)
64      get_trigger_type();
65  }
66 
67 
68  // is the object in question one we should be triggered by?
69  i4_bool triggable_object(g1_object_class *o)
70  {
71    switch (type)
72    {
73      case ANYONE:  return i4_T;
74      case TEAM_MATES: if (o->player_num==player_num) return i4_T;
75      case ENEMY: if (o->player_num!=player_num) return i4_T;
76      case SUPERTANKS: if (o->id==stank_type) return i4_T;
77      case ENEMY_SUPERTANKS: if (o->id==stank_type && o->player_num!=player_num) return i4_T;
78    }
79  }
80
81  // send our trigger message to all the object our list
82  void send_to_trigger_objects(li_symbol *sym)
83  {
84    if (sym==none.get()) return; // don't send none, it means "no message"
85 
86    li_g1_ref_list *l=li_g1_ref_list::get(objects_to_trigger());
87    int t=l->size();
88    for (int i=0; i<t; i++)
89    {
90      g1_object_class *o=l->value(i);
91      if (o)
92        o->message(sym, 0,0);
93    }       
94  }
95 
96//   void note_enter_range(g1_object_class *who, g1_fire_range_type range)
97//   {
98//     li_class_context context(vars);
99   
100//     if (range<=range_when_activated() && triggable_object(who))
101//     {     
102//       li_g1_ref_list *in_range=li_g1_ref_list::get(objects_in_range());
103//       if (!in_range->find(who))
104//       {
105//         in_range->add(who);
106       
107//         if (current_state()!=on.get())
108//         {
109//           current_state()=on.get();
110//           send_to_trigger_objects(li_symbol::get(send_on_trigger()));                   
111//         }
112//       }       
113//     }
114//   }
115
116//   void note_leave_range(g1_object_class *who, g1_fire_range_type range)
117//   {
118//     li_class_context context(vars);
119
120//     if (range>=range_when_deactivated() && triggable_object(who))
121//     {
122//       li_g1_ref_list *in_range=li_g1_ref_list::get(objects_in_range());
123//       if (in_range->find(who))
124//       {
125//         in_range->remove(who);
126       
127//         if (current_state()!=off.get())
128//         {
129//           current_state()=off.get();
130//           send_to_trigger_objects(li_symbol::get(send_on_untrigger()));                   
131//         }
132//       }     
133//     }
134//   }
135   
136 
137  void think() {}
138};
139
140void g1_trigger_init()
141{
142  stank_type=g1_get_object_type("stank");
143}
144
145static g1_object_definer<g1_trigger_class>
146trigger_def("trigger", g1_object_definition_class::EDITOR_SELECTABLE, g1_trigger_init);
147
148
149
150class g1_director_class : public g1_object_class
151{
152public:
153  g1_model_draw_parameters draw_params;
154  void draw(g1_draw_context_class *context)  { g1_model_draw(this, draw_params, context); }
155  virtual i4_float occupancy_radius() const { return draw_params.extent(); }
156 
157  g1_director_class(g1_object_type id, g1_loader_class *fp)
158    : g1_object_class(id,fp)
159  {
160    draw_params.setup("trigger");
161  }
162 
163  void think()
164  {
165    li_g1_ref_list *list=li_g1_ref_list::get(objects_to_send_next_tick());
166    while (list->size())
167    {
168      g1_object_class *o=list->value(0);
169      list->remove(o->global_id);
170      send_object(o);
171    }   
172  }
173
174  void add_to_send_list(g1_object_class *o)
175  {
176    li_g1_ref_list *list=li_g1_ref_list::get(objects_to_send_next_tick());
177    if (list->find(o)==-1)
178      list->add(o);
179   
180    request_think();
181  }
182 
183  void send_object(g1_object_class *o)
184  {
185    if (!o) return ;
186   
187    li_g1_ref_list *list=li_g1_ref_list::get(li_deploy_to());
188    int list_size=list->size(), total=0;
189
190    // count how many valid objects we point to
191    for (int i=0; i<list_size; i++)
192    {
193      g1_object_class *to=list->value(i);
194      if (to)
195        total++;
196    }
197
198    if (total)
199    {
200      // pick one of the valid destinations
201      int dest=g1_rand(56)%total;
202      total=0;
203      for (int j=0; j<list_size; j++)
204      {
205        g1_object_class *to=list->value(j);
206        if (to)
207        {
208          if (total==dest)
209          {
210            o->deploy_to(to->x, to->y);
211            return ;
212          }
213          else
214            total++;
215        }
216      }
217    }
218   
219    return ;
220  }
221 
222//   void note_enter_range(g1_object_class *who, g1_fire_range_type range)
223//   {
224//     li_class_context context(vars);
225   
226//     if (range<=range_when_deployed() &&
227//         (who_to_send()==anyone.get() ||
228//          (who->player_num==player_num && who_to_send()==team.get()) ||
229//          (who->player_num!=player_num && who_to_send()==enemy.get())))
230//     {
231//       li_g1_ref_list *r=li_g1_ref_list::get(nearby_objects());
232//       if (r->find(who)==-1)
233//       {
234//         r->add(who);
235
236//         add_to_send_list(who);
237//       }
238//     }
239//   }
240
241//   void note_leave_range(g1_object_class *who, g1_fire_range_type range)
242//   {
243//     li_class_context context(vars);
244       
245//     li_g1_ref_list *r=li_g1_ref_list::get(nearby_objects());
246//     if (r->find(who)!=-1)
247//       r->remove(who);
248//   }
249
250  li_object *message(li_symbol *message_name, li_object *message_params, li_environment *env)
251  {
252    li_class_context context(vars);
253   
254    if (message_name==on.get())
255    {
256      current_state()=on.get();
257
258      // we just turned on, see if there are any nearby object we should send
259      // to there destinations
260      li_g1_ref_list *r=li_g1_ref_list::get(nearby_objects());
261      int t=r->size();
262      for (int i=0; i<t; i++)
263        add_to_send_list(r->value(i));
264     
265    } else if (message_name==off.get())
266      current_state()=off.get();
267  }
268
269
270  // we were put down in the editor, scan for nearby objects and send them if we are on
271  i4_bool occupy_location()
272  {
273    li_class_context context(vars);
274
275    g1_object_class *olist[G1_MAX_OBJECTS];   
276    int t=g1_get_map()->get_objects_in_range(x,y, range_when_deployed(), olist, G1_MAX_OBJECTS,
277                                       0xffffffff,  g1_object_definition_class::MOVABLE);
278
279
280    li_object *o=nearby_objects();
281
282    li_g1_ref_list *r=li_g1_ref_list::get(o);
283   
284    while (r->size())
285      r->remove(r->get_id(0));
286
287    for (int i=0; i<t; i++)
288    {
289      r->add(olist[i]);
290      if (current_state()==on.get())
291        add_to_send_list(olist[i]);
292    }       
293   
294    return g1_object_class::occupy_location();
295  }
296
297 
298};
299
300static g1_object_definer<g1_director_class>
301director_def("director", g1_object_definition_class::EDITOR_SELECTABLE);
Note: See TracBrowser for help on using the repository browser.