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

Last change on this file since 494 was 494, checked in by Sam Hocevar, 10 years ago

style: remove trailing spaces, fix copyright statements.

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