source: golgotha/src/golg/objs/def_object.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: 14.3 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 "lisp/lisp.hh"
10#include "objs/miscobjs.hh"
11#include "g1_object.hh"
12#include "lisp/li_class.hh"
13#include "objs/model_id.hh"
14#include "saver.hh"
15#include "objs/model_draw.hh"
16#include "objs/def_object.hh"
17#include "li_objref.hh"
18#include "lisp/li_vect.hh"
19#include "lisp/li_dialog.hh"
20#include "map_man.hh"
21#include "map.hh"
22
23static li_symbol *s_model_name=0, *s_mini_object=0,
24  *s_offset=0, *s_position=0, *s_rotation=0,
25  *s_object_flags=0, *s_type_flags=0;
26
27
28static li_symbol *s_ofun[G1_F_TOTAL];
29
30
31////////////////////  li_def_object setup code ///////////////////////////////////////
32
33// these flag value are assigned ot their symbol names for easy ussage in script files
34static w32 g1_oflag_values[]={g1_object_class::THINKING,
35                              g1_object_class::SELECTABLE,
36                              g1_object_class::TARGETABLE,
37                              g1_object_class::GROUND,
38                              g1_object_class::UNDERWATER,
39                              g1_object_class::AERIAL,
40                              g1_object_class::HIT_GROUND,
41                              g1_object_class::HIT_UNDERWATER,
42                              g1_object_class::HIT_AERIAL,
43                              g1_object_class::BLOCKING,
44                              g1_object_class::DANGEROUS,
45                              g1_object_class::CAN_DRIVE_ON
46};
47
48static char *g1_oflag_names[]={"thinking",
49                               "selectable",
50                               "targetable",
51                               "ground",
52                               "underwater",
53                               "aerial",
54                               "hit_ground",
55                               "hit_underwater",
56                               "hit_aerial",
57                               "blocking",
58                               "dangerous",
59                               "can_drive_on",
60                               0};
61
62
63static char *g1_ofun_names[G1_F_TOTAL]={"think",
64                                         "damage",
65                                         "notify_damage",
66                                         "enter_range",
67                                         "draw",
68                                         "message",
69                                         "deploy_to",
70                                         "change_player_num",
71                                         "occupy_location",
72                                         "unoccupy_location"};
73
74li_object *li_def_object(li_object *o, li_environment *env);
75li_object *li_def_buildings(li_object *o, li_environment *env)
76{
77  for (; o; o=li_cdr(o,env))
78    g1_create_deco_object(li_string::get(li_eval(li_car(o,env), env),env)->value());
79  return 0;
80}
81
82class g1_create_object_init : public i4_init_class
83{
84public: 
85  void init()
86  {
87    int i=0;
88    for (char **a=g1_oflag_names; *a; a++)
89      li_set_value(*a, new li_int(g1_oflag_values[i++]));
90
91    for (i=0; i<G1_F_TOTAL; i++)
92      s_ofun[i]=li_get_symbol(g1_ofun_names[i]);
93   
94    li_set_value("editor_selectable", new li_int(g1_object_definition_class::EDITOR_SELECTABLE));
95    li_set_value("movable", new li_int(g1_object_definition_class::MOVABLE));
96
97
98    li_add_function("def_object", li_def_object);
99    li_add_function("def_buildings", li_def_buildings);
100  }
101
102} g1_create_object_init_instance;
103
104
105
106struct g1_object_def_struct
107{
108  char *name; 
109  char *model_name;
110  i4_array<g1_mini_object_def> *minis;
111  li_type_number var_class;
112  w32 flags;
113 
114  g1_object_def_struct()
115  {
116    name=0;
117    minis=0;
118    var_class=0;
119    flags=0;
120  } 
121} ;
122
123
124
125/////////////////////////////  Dynamic object code ///////////////////////////////
126
127void g1_mini_object_def::assign_to(g1_mini_object *m)
128{
129  m->offset=offset;
130  m->x=m->lx=position.x;
131  m->y=m->ly=position.y;
132  m->h=m->lh=position.z;
133
134  m->rotation=m->lrotation=rotation;
135  m->defmodeltype=defmodeltype;
136  m->frame=0;
137  m->animation=0;
138}
139
140g1_dynamic_object_type_class::g1_dynamic_object_type_class(li_symbol *sym)
141  : g1_object_definition_class(sym->name()->value()),
142    minis(0,1)
143
144{
145  obj_flags=g1_object_class::CAN_DRIVE_ON;
146  var_class=0;
147  flags |=  TO_DYNAMIC_OBJECT;
148
149  memset(&funs, 0, sizeof(funs));
150}
151
152
153li_object *g1_dynamic_object_class::message(li_symbol *name, li_object *params, li_environment *env)
154{
155  g1_dynamic_object_type_class *t=get_type();
156  if (t->funs[G1_F_MESSAGE])
157  {
158    li_class_context context(vars);
159    li_g1_ref _me(global_id);
160     
161    li_list *p=(li_list *)params;
162    li_push(p, name);
163    li_push(p, &_me);
164
165    return t->funs[G1_F_MESSAGE](p , env);
166  }
167  return 0;
168}
169
170
171g1_draw_context_class *g1_draw_context;
172
173// called when the object is on a map cell that is drawn
174void g1_dynamic_object_class::draw(g1_draw_context_class *context)
175{
176  g1_dynamic_object_type_class *t=get_type();
177  if (t->funs[G1_F_DRAW])
178  {
179    g1_draw_context=context;
180    li_class_context context(vars);
181    li_g1_ref _me(global_id);
182    t->funs[G1_F_DRAW](li_make_list(&_me,0),0);
183  }
184  else
185  {
186    g1_model_draw_parameters mp;
187    mp.model=get_type()->model;
188    g1_model_draw(this, mp, context);
189  }
190}
191
192
193// void g1_dynamic_object_class::note_enter_range(g1_object_class *who, g1_fire_range_type range)
194// {
195//   g1_dynamic_object_type_class *t=get_type();
196//   if (t->funs[G1_F_ENTER_RANGE])
197//   {
198//     li_class_context context(vars);
199//     t->funs[G1_F_ENTER_RANGE](li_make_list(new li_g1_ref(global_id),
200//                                            new li_g1_ref(who->global_id),
201//                                            new li_int(range), 0), 0);
202//   }
203// }
204
205void g1_dynamic_object_class::damage(g1_object_class *obj, int hp, i4_3d_vector damage_dir)
206{
207  g1_dynamic_object_type_class *t=get_type();
208  if (t->funs[G1_F_DAMAGE])
209  {
210    li_class_context context(vars);   
211    t->funs[G1_F_DAMAGE](li_make_list(new li_g1_ref(global_id),
212                                      new li_g1_ref(obj->global_id),
213                                      new li_int(hp),
214                                      new li_vect(damage_dir), 0),0);
215  }
216  else
217    request_think();
218}
219
220void g1_dynamic_object_class::notify_damage(g1_object_class *obj, int hp, w32 notes)
221{
222  g1_dynamic_object_type_class *t=get_type();
223  if (t->funs[G1_F_NOTIFY_DAMAGE])
224  {
225    li_class_context context(vars);   
226    t->funs[G1_F_NOTIFY_DAMAGE](li_make_list(new li_g1_ref(global_id),
227                                             new li_g1_ref(obj->global_id),
228                                             new li_int(hp),
229                                             new li_int(notes), 0),0);
230  }
231  else
232    g1_object_class::notify_damage(obj, hp);
233}
234
235void g1_dynamic_object_class::think()
236{
237  g1_dynamic_object_type_class *t=get_type();
238  if (t->funs[G1_F_THINK])
239  {
240    li_class_context context(vars);   
241    t->funs[G1_F_THINK](li_make_list(new li_g1_ref(global_id), 0), 0);
242  }
243}
244
245
246static li_float_class_member dest_x("dest_x"), dest_y("dest_y");
247
248i4_bool g1_dynamic_object_class::deploy_to(float x, float y)
249{
250  g1_dynamic_object_type_class *t=get_type();
251  li_class_context context(vars);
252
253  if (t->funs[G1_F_DEPLOY_TO])
254    t->funs[G1_F_DEPLOY_TO](li_make_list(new li_g1_ref(global_id),
255                                         new li_float(x),
256                                         new li_float(y),0), 0);
257  else
258  {
259    if (vars && vars->member_offset(dest_x)!=-1)
260    {
261      dest_x()=x;
262      dest_y()=y;
263    }
264  }
265  return 0;
266}
267
268
269
270void g1_dynamic_object_class::change_player_num(int new_player)
271{
272  g1_dynamic_object_type_class *t=get_type();
273  if (t->funs[G1_F_CHANGE_TEAMS])
274  {
275    li_class_context context(vars);
276    t->funs[G1_F_CHANGE_TEAMS](li_make_list(new li_g1_ref(global_id),
277                                            new li_int(new_player), 0), 0);
278  }
279  else
280    g1_object_class::change_player_num(new_player); 
281}
282
283i4_bool g1_dynamic_object_class::occupy_location()
284{
285  g1_dynamic_object_type_class *t=get_type();
286  if (t->funs[G1_F_OCCUPY_LOCATION])
287  {
288    li_class_context context(vars);
289
290    if (t->funs[G1_F_OCCUPY_LOCATION](li_make_list(new li_g1_ref(global_id),0), 0))
291      return i4_T;
292    else return i4_F;
293  }
294  else
295    return g1_object_class::occupy_location(); 
296}
297
298
299void g1_dynamic_object_class::unoccupy_location()
300{
301  g1_dynamic_object_type_class *t=get_type();
302  if (t->funs[G1_F_UNOCCUPY_LOCATION])
303  {
304    li_class_context context(vars);
305    t->funs[G1_F_UNOCCUPY_LOCATION](li_make_list(new li_g1_ref(global_id), 0), 0);
306  }
307  else
308    g1_object_class::unoccupy_location(); 
309}
310
311
312g1_dynamic_object_class::g1_dynamic_object_class(g1_object_type type, g1_loader_class *fp)
313  : g1_object_class(type, fp)
314
315{
316  g1_dynamic_object_type_class *dtype=get_type();
317       
318  if (dtype->minis.size())
319  {
320    allocate_mini_objects(dtype->minis.size(), "");
321    for (int i=0; i<dtype->minis.size(); i++)
322      dtype->minis[i].assign_to(mini_objects+i);     
323  }
324
325
326  if (fp && fp->read_16()==VERSION)
327  {
328    int old_minis=fp->read_8(), i;
329    int old_mini_disk_size=fp->read_32();
330     
331    if (old_minis==dtype->minis.size())
332    {
333      g1_mini_object *m=mini_objects;
334
335      for (i=0; i<dtype->minis.size(); i++)
336      {
337        fp->read_format("fffffffff",
338                        &m->offset.x, &m->offset.y, &m->offset.z,
339                        &m->x, &m->y, &m->h,
340                        &m->rotation.x, &m->rotation.y, &m->rotation.z);
341      }
342    }
343    else
344      fp->seek(fp->tell() + old_mini_disk_size);
345  }
346
347
348  flags = get_type()->obj_flags;
349
350  grab_old();
351}
352
353
354void g1_dynamic_object_class::save(g1_saver_class *fp)
355{
356  g1_object_class::save(fp);
357
358  fp->write_16(VERSION);
359
360  fp->write_8(num_mini_objects);
361  int han=fp->mark_size();
362
363  g1_mini_object *m=mini_objects;
364  for (int i=0; i<num_mini_objects; i++)
365  {     
366    fp->write_format("fffffffff",
367                     &m->offset.x, &m->offset.y, &m->offset.z,
368                     &m->x, &m->y, &m->h,
369                     &m->rotation.x, &m->rotation.y, &m->rotation.z);
370  }
371
372  fp->end_mark_size(han);
373}
374
375
376
377
378//////////////////  dynamic object type functions ///////////////////////////////
379
380g1_object_class *g1_dynamic_object_type_class::create_object(g1_object_type type,
381                                                             g1_loader_class *fp)
382{
383  g1_object_class *o=new g1_dynamic_object_class(type, fp);   
384  o->init();
385  return o;
386}
387
388static void read_vect(i4_3d_vector &v, li_object *o, li_environment *env)
389{
390  v.x=li_get_float(li_eval(li_car(o,env), env),env);  o=li_cdr(o,env);
391  v.y=li_get_float(li_eval(li_car(o,env), env),env);  o=li_cdr(o,env);
392  v.z=li_get_float(li_eval(li_car(o,env), env),env);
393}
394
395
396static li_function_type get_function(li_object *o, li_environment *env)
397{
398  li_object *fun=li_get_fun(li_symbol::get(o,env),env);
399  if (!fun)
400    li_error(env, "no registered function %O", o);
401
402  return li_function::get(fun,env)->value();
403}
404
405li_object *li_def_object(li_object *o, li_environment *env)
406{
407  li_symbol *sym=li_symbol::get(li_car(o,env),env);
408 
409
410  g1_dynamic_object_type_class *type=new g1_dynamic_object_type_class(sym);
411
412
413  for (li_object *l=li_cdr(o,env); l; l=li_cdr(l,env))
414  {
415    li_object *prop=li_car(l,env);
416    li_symbol *sym=li_symbol::get(li_car(prop,env),env);
417    prop=li_cdr(prop,env);
418
419    if (sym==li_get_symbol("model_name", s_model_name))
420    {
421      int id=g1_model_list_man.find_handle(li_string::get(li_car(prop,env),env)->value());
422      type->model=g1_model_list_man.get_model(id);
423    }
424    else if (sym==li_get_symbol("mini_object", s_mini_object))
425    {
426      g1_mini_object_def mo;
427      mo.init();
428         
429      char *name=0;
430      for (;prop; prop=li_cdr(prop,env)) // prop = ((offset 0 0 0.1) (center 0 0 0) "gunport_barrel")
431      {
432        li_object *sub=li_car(prop,env);
433        sym=li_symbol::get(li_car(sub,env),env); sub=li_cdr(sub,env);
434
435
436        if (sym==li_get_symbol("offset", s_offset))
437          read_vect(mo.offset, sub, env);
438        else if (sym==li_get_symbol("position", s_position))
439          read_vect(mo.position, sub, env);
440        else if (sym==li_get_symbol("rotation", s_rotation))
441          read_vect(mo.rotation, sub, env);
442        else if (sym==li_get_symbol("model_name", s_model_name))
443        {
444          char *n=li_string::get(li_eval(li_car(sub,env), env),env)->value();
445          mo.defmodeltype=g1_model_list_man.find_handle(n);
446        }
447        else li_error(env,"%O should be (offset/position/rotation x y z)",sym);
448      }
449
450      type->minis.add(mo);
451
452    }
453    else if (sym==li_get_symbol("object_flags", s_object_flags))
454    {
455      for (;prop; prop=li_cdr(prop,env))
456        type->obj_flags |= li_int::get(li_eval(li_car(prop,env),env),env)->value();
457    }
458    else if (sym==li_get_symbol("type_flags", s_type_flags))
459    {
460      for (;prop; prop=li_cdr(prop,env))
461        type->flags |= li_int::get(li_eval(li_car(prop,env),env),env)->value();
462    }
463    else
464    {
465      int found=0;
466      for (int i=0; i<G1_F_TOTAL; i++)
467        if (sym==s_ofun[i])
468        {
469          type->funs[i]=get_function(li_car(prop,env),env);
470          found=1;
471        }
472
473      if (!found)
474        li_error(env,"unknown object property %O", sym);
475    }     
476  }   
477
478  // if functions were not filled in see if we can find defaults
479  for (int i=0; i<G1_F_TOTAL; i++)
480    if (type->funs[i]==0)
481    {
482      char buf[200];
483      sprintf(buf, "%s_%s", type->name(), g1_ofun_names[i]);
484     
485      li_symbol *sym=li_find_symbol(buf);
486      if (sym)
487      {
488        li_function *fun=li_function::get(sym->fun(), env);
489        if (fun)
490          type->funs[i]=li_function::get(fun, env)->value();
491      }
492    }
493
494
495  type->flags|=g1_object_definition_class::DELETE_WITH_LEVEL;
496 
497  return 0;
498}
499
500
501
Note: See TracBrowser for help on using the repository browser.