source: abuse/branches/pd/macabuse/src/chars.c @ 161

Last change on this file since 161 was 49, checked in by Sam Hocevar, 15 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 13.7 KB
Line 
1#include "chars.hpp"
2#include "game.hpp"
3#include "intsect.hpp"
4#include "lisp.hpp"
5#include "jwindow.hpp"
6#include "input.hpp"
7#include "id.hpp"
8#include "clisp.hpp"
9#include "dprint.hpp"
10#include "lisp_gc.hpp"
11
12#define FADING_FRAMES 26
13#define FADING_MAX 32
14
15character_type **figures;
16
17
18
19int total_weapons=0;
20int *weapon_types=NULL;    // maps 0..total_weapons into 'real' weapon type
21
22char *state_names[MAX_STATE]= {
23                               "dead",
24                               "dieing",
25                               "stopped",
26                               "start_run_jump","run_jump","run_jump_fall","end_run_jump",
27                               "flinch_up","flinch_down",
28                               "morph_pose",
29                               "running" };
30
31/*                             "start_still_jump","still_jump","still_jump_fall","end_still_jump",
32
33                               "morph_pose",
34                               
35                               "walking",
36                               
37
38                               "weapon_draw",
39                               "weapon_put_away",
40                               "weapon_fire",
41                               "weapon_end_fire",
42                               "weapon_fire_up",
43                               "weapon_end_fire_up",
44
45                               "blocking",
46                               "block_recoil",
47
48                               "turn_around",
49                               "flinch_up","flinch_down","flinch_back",
50                               "flinch_air","flinch_ground","flinch_getup","woze",
51                               "stance"
52                             } ; */
53
54
55char *cflag_names[TOTAL_CFLAGS]={"hurt_all","is_weapon","stoppable","can_block",
56                                 "hurtable","pushable","unlistable",
57                                 "add_front","cached_in","need_cache_in","unactive_shield"};
58char *ofun_names[TOTAL_OFUNS]={"ai_fun","move_fun","draw_fun","map_draw_fun","damage_fun",
59                               "next_state_fun","user_fun",
60                               "constructor","reload_fun","get_cache_list_fun",
61                               "type_change_fun"};
62
63int character_type::add_state(void *symbol)             // returns index into seq to use
64{
65  if (item_type(symbol)!=L_SYMBOL)
66  {
67    lprint(symbol);
68    lbreak("is not a symbol (in def_char)");
69    exit(0);
70  }
71
72  void *val=symbol_value(symbol);
73
74  int num;
75  if (DEFINEDP(val))
76  {
77    if (item_type(val)!=L_NUMBER)
78    {
79      lprint(symbol);
80      dprintf("expecting symbol value to be a number, instead got : ");
81      lprint(val);
82      lbreak("");
83      exit(0);
84    }
85    num=lnumber_value(val);
86  } else
87  {
88    num=ts;
89    if (num<MAX_STATE) num=MAX_STATE;
90    int sp=current_space;
91    current_space=PERM_SPACE;
92    set_symbol_number(symbol,num);
93    current_space=sp;
94  }
95
96  if (num<ts && seq[num])
97  {
98    lprint(symbol);
99    lbreak("symbol has been assigned value %d, but value already in use by state %s\n"
100           "use a different symbol for this state\n",
101           lstring_value(symbol_name(seq_syms[num])));
102    exit(0);
103  } else if (num>=ts)
104  {
105    seq=(sequence **)jrealloc(seq,sizeof(sequence *)*(num+1),"state list");   
106    seq_syms=(void **)jrealloc(seq_syms,sizeof(void *)*(num+1),"state sym list");   
107
108    memset(&seq[ts],0,sizeof(sequence *)*((num+1)-ts));
109    memset(&seq_syms[ts],0,sizeof(void *)*((num+1)-ts));
110
111    ts=num+1;
112  }
113
114  seq_syms[num]=symbol;
115  return num;
116}
117
118int flinch_state(character_state state)
119{
120  if (state==flinch_up || state==flinch_down)
121    return 1;
122  else return 0;
123}
124
125int character_type::cache_in()    // returns false if out of cache memory
126{
127  int i;
128  if (get_cflag(CFLAG_CACHED_IN))
129    return 1;
130  cflags|=1<<CFLAG_CACHED_IN;
131
132  for (i=0;i<ts;i++)
133  {
134    if (seq[i])
135      seq[i]->cache_in();
136  }
137  return 1;
138}
139
140void character_type::add_sequence(character_state which, sequence *new_seq)
141{
142  if (seq[which])
143    delete seq[which];
144  seq[which]=new_seq; 
145
146
147void *l_obj_get(long number) // exten lisp function switches on number
148{
149  character_type *t=figures[current_object->otype];
150  if (t->tiv<=number || !t->vars[number])
151  {
152    lbreak("access : variable does not exsist for this class\n");
153    return 0;
154  }
155  return new_lisp_number(current_object->lvars[t->var_index[number]]); 
156}
157
158void l_obj_set(long number, void *arg)  // exten lisp function switches on number
159{
160  character_type *t=figures[current_object->otype];
161  if (t->tiv<=number || !t->vars[number])
162  {
163    lbreak("set : variable does not exsist for this class\n");
164    return;
165  }
166  current_object->lvars[t->var_index[number]]=lnumber_value(arg);
167}
168
169void l_obj_print(long number)  // exten lisp function switches on number
170{
171  character_type *t=figures[current_object->otype];
172  if (t->tiv<=number || !t->vars[number])
173  {
174    lbreak("access : variable does not exsist for this class\n");
175    return;
176  }
177  dprintf("%d",current_object->lvars[t->var_index[number]]); 
178}
179
180void character_type::add_var(void *symbol, void *name)
181{
182  /* First see if the variable has been defined for another object
183     if so report a conflict if any occur */
184  lisp_symbol *s=(lisp_symbol *)symbol;
185  if (DEFINEDP(s->value) && (item_type(s->value)!=L_OBJECT_VAR))
186  {
187    lprint(symbol);
188    lbreak("symbol already has a value, cannot instantiate an object varible");
189    exit(0);
190  } else if (DEFINEDP(s->value))
191  {
192    int index=((lisp_object_var *)s->value)->number;
193    if (index<tiv)
194    {
195      if (vars[index])
196      {       
197        lbreak("While defining object %s :\n"
198               "  var '%s' was previously defined by another\n"
199               "  with index %d, but %s has a var listed '%s' with same index\n"
200               "  try moving definition of %s before previously declared object",
201               lstring_value(symbol_name(name)),
202               lstring_value(symbol_name(symbol)),
203               index,
204               lstring_value(symbol_name(name)),
205               lstring_value(symbol_name(vars[index])),
206               lstring_value(symbol_name(name))
207               );
208        exit(0);
209      } else
210      {
211        var_index[index]=tv;
212        vars[index]=symbol;
213        tv++;
214      }
215    } else
216    {
217      int new_total=index+1;
218      vars=(void **)jrealloc(vars,sizeof(void *)*new_total,"variable name list");
219      var_index=(short *)jrealloc(var_index,sizeof(short)*new_total,"variable index");
220      memset(&vars[tiv],0,(new_total-tiv)*sizeof(void *));
221      memset(&var_index[tiv],0,(new_total-tiv)*sizeof(short));
222      tiv=new_total;
223
224      var_index[index]=tv;
225      vars[index]=symbol;
226      tv++;
227    }   
228  } else  /** Nope, looks like we have to add the variable ourself and define the assesor funs */
229  {
230    /* locate a free index in the index list */
231    int free_index=tiv;
232    for (int i=0;i<tiv;i++)
233      if (!vars[i] && i<tiv) free_index=i;
234    if (free_index==tiv)
235    {
236      int new_total=free_index+1;
237      vars=(void **)jrealloc(vars,sizeof(void *)*new_total,"variable name list");
238      var_index=(short *)jrealloc(var_index,sizeof(short)*new_total,"variable index");
239      memset(&vars[tiv],0,(new_total-tiv)*sizeof(void *));
240      memset(&var_index[tiv],0,(new_total-tiv)*sizeof(short));
241      tiv=new_total;
242    }
243
244    /* create the var and add to var list */
245    int sp=current_space;
246    current_space=PERM_SPACE;
247
248    add_c_object(symbol,free_index);
249   
250    vars[free_index]=symbol;
251    var_index[free_index]=tv;
252    tv++;
253    current_space=sp;
254  }
255}
256
257
258long character_type::isa_var_name(char *name)
259{
260  int i=0;
261  for (;i<TOTAL_OBJECT_VARS;i++)
262  {
263    if (!strcmp(object_descriptions[i].name,name))
264      return 1;
265  }
266  for (i=0;i<tiv;i++)
267    if (!strcmp(lstring_value(symbol_name(vars[i])),name))
268      return 1;
269  return 0;
270}
271
272character_type::character_type(void *args, void *name)
273{
274  p_ref r2(args);
275  int i;
276  ts=tv=0;
277  seq=NULL;
278  seq_syms=NULL;
279  vars=NULL;
280  var_index=NULL;
281  tiv=0;
282
283  void *l_abil=  make_find_symbol("abilities");
284  void *l_funs=  make_find_symbol("funs");
285  void *l_states=make_find_symbol("states");
286  void *l_flags= make_find_symbol("flags");
287  void *l_range= make_find_symbol("range");
288  void *l_draw_range= make_find_symbol("draw_range");
289  void *l_fields=make_find_symbol("fields");
290  void *l_logo=  make_find_symbol("logo");
291  void *l_vars=  make_find_symbol("vars");
292
293  memset(fun_table,0,sizeof(fun_table));     // destory all hopes of fun
294  fields=NULL;
295  cflags=0;
296  morph_mask=-1;
297  morph_power=0;
298  total_fields=0;
299  logo=-1;
300  rangex=rangey=0;
301  draw_rangex=draw_rangey=0;
302
303  for (i=0;i<TOTAL_ABILITIES;i++)
304    abil[i]=get_ability_default((ability)i);         
305  void *field=args;
306  p_ref r7(field);
307  for (;field;field=CDR(field))
308  {
309    void *f=CAR(CAR(field));
310    p_ref r1(f);
311   
312    if (f==l_abil)
313    {
314      void *l=CDR(CAR(field));
315      p_ref r4(l);
316      for (i=0;i<TOTAL_ABILITIES;i++)
317      {
318        Cell *ab=assoc(make_find_symbol(ability_names[i]),l);
319        p_ref r5(ab);
320        if (!NILP(ab))
321          abil[i]=lnumber_value(eval(lcar(lcdr(ab))));
322      }
323    } else if (f==l_funs)
324    {
325      void *l=CDR(CAR(field));
326      p_ref r4(l);
327      for (i=0;i<TOTAL_OFUNS;i++)
328      {
329        Cell *ab=assoc(make_find_symbol(ofun_names[i]),l);
330        p_ref r5(ab);
331        if (!NILP(ab) && lcar(lcdr(ab)))
332        fun_table[i]=lcar(lcdr(ab));
333      }
334    } else if (f==l_flags)
335    {
336      void *l=CDR(CAR(field));
337      p_ref r4(l);
338      for (i=0;i<TOTAL_CFLAGS;i++)
339      {
340        Cell *ab=assoc(make_find_symbol(cflag_names[i]),l);
341        p_ref r5(ab);
342        if (!NILP(ab) && eval(lcar(lcdr(ab))))
343        cflags|=(1<<i);
344      }
345     
346      if (get_cflag(CFLAG_IS_WEAPON))  // if this is a weapon add to weapon array
347      {
348        total_weapons++;
349        weapon_types=(int *)jrealloc(weapon_types,sizeof(int)*total_weapons,"weapon map");
350        weapon_types[total_weapons-1]=total_objects;
351      }
352    } else if (f==l_range)
353    {
354      rangex=lnumber_value(eval(lcar(lcdr(lcar(field)))));
355      rangey=lnumber_value(eval(lcar(lcdr(lcdr(lcar(field))))));
356    } else if (f==l_draw_range)
357    {
358      draw_rangex=lnumber_value(eval(lcar(lcdr(lcar(field)))));
359      draw_rangey=lnumber_value(eval(lcar(lcdr(lcdr(lcar(field))))));
360    } else if (f==l_states)
361    {
362      void *l=CDR(CAR(field));
363      p_ref r4(l);
364      char fn[100];
365      strcpy(fn,lstring_value(eval(CAR(l)))); l=CDR(l);
366      while (l)
367      {
368        seq[add_state(CAR((CAR(l))))]=new sequence(fn,eval(CAR(CDR(CAR(l)))),NULL);
369        l=CDR(l);
370      }
371    } else if (f==l_fields)
372    {
373      void *mf=CDR(CAR(field));
374      p_ref r4(mf);
375      while (!NILP(mf))
376      {
377        char *real=lstring_value(eval(lcar(lcar(mf))));
378        char *fake=lstring_value(eval(lcar(lcdr(lcar(mf)))));
379        if (!isa_var_name(real))
380        {
381          lprint(field);
382          lbreak("fields : no such var name \"%s\"\n",name);
383          exit(0);
384        }
385        total_fields++;
386
387        fields=(named_field **)jrealloc(fields,sizeof(named_field *)*total_fields,"named_fields");
388        fields[total_fields-1]=new named_field(real,fake);
389        mf=lcdr(mf);
390      }
391    } else if (f==l_logo)
392    {
393      char *fn=lstring_value(eval(CAR(CDR(CAR(field)))));
394      char *o=lstring_value(eval(CAR(CDR(CDR(CAR(field))))));
395      logo=cash.reg(fn,o,SPEC_IMAGE,1);
396    } else if (f==l_vars)
397    {
398      void *l=CDR(CAR(field));
399      p_ref r8(l);
400      while (l)
401      {
402        add_var(CAR(l),name);
403        l=CDR(l);
404      }       
405    }
406    else
407    {
408      lprint(lcar(field));
409      lbreak("Unknown field for character definiltion");
410      exit(0);
411    }   
412  }
413
414  if (!seq[stopped])
415    lbreak("object (%s) has no stopped state, please define one!\n",
416           lstring_value(symbol_name(name)));
417
418/*  char *fn=lstring_value(lcar(desc));
419  if (!fn)
420  {
421    dprintf("No filename given for def-character (%s)\n",name);
422    exit(0);
423  }
424  desc=lcdr(desc);  //  skip filename
425
426
427  Cell *mrph=assoc(l_morph,desc);     // check for morph info
428  morph_power=0;
429  if (!NILP(mrph))
430  {
431    mrph=lcdr(mrph);
432    morph_mask=cash.reg_object(fn,lcar(mrph),SPEC_IMAGE,1);
433    morph_power=lnumber_value(lcar(lcdr(mrph)));
434  } else morph_mask=-1;
435
436  Cell *sa=assoc(l_state_art,desc);
437  if (NILP(sa))
438  {
439    dprintf("missing state state art in def-character (%s)\n",name);
440    exit(0);
441  }
442 
443  sa=lcdr(sa);   // list of state sequences
444  while (!NILP(sa))
445  {
446    int num=lnumber_value(lcar(lcar(sa)));
447    if (seq[num])   
448      dprintf("Warning : state '%s' defined multiply for object %s\n"
449             "          using first definition\n",state_names[num],name);
450    else   
451      seq[lnumber_value(lcar(lcar(sa)))]=new sequence(fn,lcar(lcdr(lcar(sa))),lcar(lcdr(lcdr(lcar(sa)))));
452    sa=lcdr(sa);   
453  }
454
455  Cell *range=assoc(l_range,desc);
456  if (!NILP(range))
457  {
458    rangex=lnumber_value(lcar(lcdr(range)));
459    rangey=lnumber_value(lcar(lcdr(lcdr(range))));
460  } else
461  {
462    rangex=100;
463    rangey=50;
464  }
465
466
467
468
469  Cell *mf=assoc(l_fields,desc);
470  if (!NILP(mf))
471  {
472    mf=lcdr(mf);
473    total_fields=0;
474    while (!NILP(mf))
475    {
476      char *name=lstring_value(lcar(lcar(mf)));
477      int t=default_simple.total_vars(),find=-1;
478      for (int i=0;find<0 && i<t;i++)
479        if (!strcmp(default_simple.var_name(i),name))
480          find=i;
481      if (find<0)
482      {
483        lprint(assoc(l_fields,desc));
484        dprintf("fields : no such var name \"%s\"\n",name);
485        dprintf("current possiblities are : \n");
486        for (int i=0;i<t;i++) dprintf("\"%s\" ",default_simple.var_name(i));
487        dprintf("\n");
488        exit(0);
489      }
490      char *new_name=lstring_value(lcar(lcdr(lcar(mf))));
491      total_fields++;
492
493      fields=(named_field **)jrealloc(fields,sizeof(named_field *)*total_fields,"named_fields");
494      fields[total_fields-1]=new named_field(find,new_name);
495      mf=lcdr(mf);
496    }
497  } else total_fields=0;
498
499
500  Cell *lg=assoc(l_logo,desc);
501  if (NILP(lg))
502  {
503    if (get_cflag(CFLAG_IS_WEAPON))
504    {
505      lprint(desc);
506      lbreak("object must have a logo defined if it is a weapon\n"
507             "example '(logo . (""art/misc.spe"" . ""big waepon""))\n");
508    }
509    logo=-1;
510  }
511  else
512    logo=cash.reg_object(fn,lcdr(lg),SPEC_IMAGE,1); 
513    */
514}
515
516
517sequence *character_type::get_sequence(character_state s)
518{
519  if (seq[s])
520    return seq[s];
521  else return seq[stopped];
522}
523
524
525character_type::~character_type()
526{
527  for (int i=0;i<ts;i++) 
528    if (seq[i])
529      delete seq[i];
530  if (ts) jfree(seq);
531
532  if (total_fields)
533  {
534    for (int i=0;i<total_fields;i++)
535      delete fields[i];
536    jfree(fields);
537  }
538
539  if (ts)
540    jfree(seq_syms);
541 
542  if (tiv)
543  {
544    jfree(vars);
545    jfree(var_index);
546  }
547
548
549}
550
551extern long small_ptr_size(void *ptr);
552
553
554void chk_sizes()
555{
556  for (int i=0;i<total_objects;i++)
557  {
558    figures[i]->check_sizes();
559  }
560}
561
562
563void character_type::check_sizes()
564{
565  for (int i=0;i<ts;i++)
566    if (seq[i] && small_ptr_size(seq[i])!=8)
567      dprintf("bad size for state %d\n",i);
568}
569
570
571
572
Note: See TracBrowser for help on using the repository browser.