source: abuse/trunk/src/chars.cpp @ 579

Last change on this file since 579 was 555, checked in by Sam Hocevar, 11 years ago

ps3: make everything compile on the PS3. Of course, nothing links yet
because so much support is missing.

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