source: abuse/tags/pd/abuse/src/newlight.c @ 49

Last change on this file since 49 was 49, checked in by Sam Hocevar, 11 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 19.5 KB
Line 
1#include "light.hpp"
2#include <stdlib.h>
3#include "image.hpp"
4#include "macs.hpp"
5#include "video.hpp"
6#include "palette.hpp"
7#include "timing.hpp"
8#include "specs.hpp"
9#include "dprint.hpp"
10#include "filter.hpp"
11#include "video.hpp"
12
13light_source *first_light_source=NULL;
14unsigned char *white_light,*green_light;
15unsigned short min_light_level=0;
16extern int vmode;
17
18int light_detail=MEDIUM_DETAIL;
19
20long light_to_number(light_source *l)
21{
22 
23  if (!l) return 0;
24  int x=1;
25  for (light_source *s=first_light_source;s;s=s->next,x++)
26    if (s==l) return x;
27  return 0;
28}
29
30
31light_source *number_to_light(long x)
32{
33  if (x==0) return NULL;
34  x--;
35  for (light_source *s=first_light_source;x && s;x--,s=s->next);
36  return s;       
37}
38
39light_source *light_source::copy()
40{
41  next=new light_source(type,x,y,inner_radius,outer_radius,xshift,yshift,next);
42  return next;
43}
44
45void delete_all_lights()
46{
47  while (first_light_source)
48  {
49    light_source *p=first_light_source;
50    first_light_source=first_light_source->next;
51    delete p;
52  }
53}
54
55void delete_light(light_source *which)
56{
57  if (which==first_light_source)
58  {
59    first_light_source=first_light_source->next;
60    delete which;
61  }
62  else
63  {
64    for (light_source *f=first_light_source;f->next!=which && f;f=f->next);
65    if (f)
66    {
67      f->next=which->next;
68      delete which;
69    }
70  }
71}
72
73void light_source::calc_range()
74{
75  switch (type)
76  {
77    case 0 :
78    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
79      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
80    } break;
81    case 1 :
82    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
83      x2=x+(outer_radius>>xshift); y2=y;
84    } break;
85    case 2 :
86    { x1=x-(outer_radius>>xshift); y1=y;
87      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
88    } break;
89    case 3 :
90    { x1=x; y1=y-(outer_radius>>yshift);
91      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
92    } break;
93    case 4 :
94    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
95      x2=x; y2=y+(outer_radius>>yshift);
96    } break;
97
98
99    case 5 :
100    { x1=x; y1=y-(outer_radius>>yshift);
101      x2=x+(outer_radius>>xshift); y2=y;
102    } break;
103    case 6 :
104    { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
105      x2=x; y2=y;
106    } break;
107    case 7 :
108    { x1=x-(outer_radius>>xshift); y1=y;
109      x2=x; y2=y+(outer_radius>>yshift);
110    } break;
111    case 8 :
112    { x1=x; y1=y;
113      x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
114    } break;
115    case 9 :
116    {
117      x1=x;
118      y1=y;
119      x2=x+xshift;
120      y2=y+yshift;
121    } break;
122
123  }
124  mul_div=(1<<16)/(outer_radius-inner_radius)*64;
125}
126
127light_source::light_source(char Type, long X, long Y, long Inner_radius,
128                           long Outer_radius, long Xshift,  long Yshift, light_source *Next)
129{
130  type=Type;
131  x=X; y=Y;
132  inner_radius=Inner_radius; 
133  outer_radius=Outer_radius;
134  next=Next;
135  known=0;
136  xshift=Xshift;
137  yshift=Yshift;
138  calc_range();
139}
140
141light_source *add_light_source(char type, long x, long y,
142                               long inner, long outer, long xshift, long yshift)
143{
144  first_light_source=new light_source(type,x,y,inner,outer,xshift,yshift,first_light_source);
145  return first_light_source;
146}
147
148
149#define TTINTS 9
150uchar *tints[TTINTS];
151
152void calc_tint(uchar *tint, int rs, int gs, int bs, int ra, int ga, int ba, palette *pal)
153{
154  palette npal;
155  memset(npal.addr(),0,256);
156  for (int i=0;i<256;i++)
157  {
158    npal.set(i,(int)rs,(int)gs,(int)bs);
159    rs+=ra; if (rs>255) rs=255; if (rs<0) rs=0;
160    gs+=ga; if (gs>255) gs=255; if (gs<0) gs=0;
161    bs+=ba; if (bs>255) bs=255; if (bs<0) bs=0;
162  }
163  filter f(pal,&npal);
164  filter f2(&npal,pal);
165
166  for (i=0;i<256;i++,tint++)
167    *tint=f2.get_mapping(f.get_mapping(i));
168}
169
170
171void calc_light_table(palette *pal)
172{
173  white_light=(unsigned char *)jmalloc(256*64,"light table");
174  green_light=(unsigned char *)jmalloc(256*64,"green light");
175  for (int i=0;i<TTINTS;i++)
176      tints[i]=(uchar *)jmalloc(256,"color tint");
177
178  jFILE fp("light.tbl","rb");
179  int recalc=0;
180  if (fp.open_failure()) recalc=1;
181  else
182  {
183    if (fp.read_short()!=calc_crc((unsigned char *)pal->addr(),768))
184      recalc=1;
185    else
186    {
187      fp.read(white_light,256*64);
188      fp.read(green_light,256*64);
189      for (i=0;i<TTINTS;i++)
190        fp.read(tints[i],256);
191    }
192  }
193
194  if (recalc)
195  { 
196    fprintf(stderr,"Palette has changed, recalculating light table...\n");
197    fprintf(stderr,"white : ");
198    for (int color=0;color<256;color++)
199    {
200      unsigned char r,g,b;
201      pal->get(color,r,g,b);
202      if (color%16==0)
203        fprintf(stderr,"%d ",color);
204      for (int intensity=63;intensity>=0;intensity--)
205      {
206        if (r>0 || g>0 || b>0)
207          white_light[intensity*256+color]=pal->find_closest(r,g,b);
208        else
209          white_light[intensity*256+color]=0;
210        if (r) r--;  if (g) g--;  if (b) b--;   
211      }
212    }
213
214    fprintf(stderr,"green : ");
215    for (color=0;color<256;color++)
216    {
217      unsigned char r,g,b;
218      pal->get(color,r,g,b);
219      r=r*3/5; b=b*3/5; g+=7; if (g>255) g=255;
220      if (color%16==0)
221        fprintf(stderr,"%d ",color);
222      for (int intensity=63;intensity>=0;intensity--)
223      {
224        if (r>0 || g>0 || b>0)
225          green_light[intensity*256+color]=pal->find_closest(r,g,b);
226        else
227          green_light[intensity*256+color]=0;
228        if (r) r--; 
229        if ((intensity&1)==1)
230          if (g) g--; 
231        if (b) b--;     
232      }
233    }
234
235    dprintf("\ncalculating tints : \n");
236    uchar t[TTINTS*6]={0,0,0,0,0,0, // normal
237                   0,0,0,1,0,0,     // red
238                   0,0,0,1,1,0,     // yellow
239                   0,0,0,1,0,1,     // purple
240                   0,0,0,1,1,1,     // gray
241                   0,0,0,0,1,0,     // green
242                   0,0,0,0,0,1,     // blue
243                   0,0,0,0,1,1,     // cyan
244
245
246
247
248
249
250                   0,0,0,0,0,0   // reverse green  (night vision effect)
251                 } ;
252    uchar *ti=t+6;
253    uchar *c;
254    for (i=0,c=tints[0];i<256;i++,c++) *c=i;  // make the normal tint (maps everthing to itself)
255    for (i=0,c=tints[TTINTS-1];i<256;i++,c++)  // reverse green
256    {
257      int r=pal->red(i)/2,g=255-pal->green(i)-30,b=pal->blue(i)*3/5+50;
258      if (g<0) g=0;
259      if (b>255) b=0;
260      *c=pal->find_closest(r,g,b);
261    }
262
263    // make the colored tints
264    for (i=1;i<TTINTS-1;i++)
265    {
266      calc_tint(tints[i],ti[0],ti[1],ti[2],ti[3],ti[4],ti[5],pal);
267      ti+=6;
268    }
269
270   
271
272    jFILE f("light.tbl","wb");
273    f.write_short(calc_crc((unsigned char *)pal->addr(),768));
274    f.write(white_light,256*64);
275    f.write(green_light,256*64);
276    for (int i=0;i<TTINTS;i++)
277      f.write(tints[i],256);
278  }
279}
280
281
282light_patch *light_patch::copy(light_patch *Next)
283{
284  light_patch *p=new light_patch(x1,y1,x2,y2,Next);
285  p->total=total;
286  if (total)   
287  {
288    p->lights=(light_source **)jmalloc(total*sizeof(light_source *),"light patches");
289    memcpy(p->lights,lights,total*(sizeof(light_source *)));
290  }
291  else
292    p->lights=NULL;
293  return p;
294}
295
296#define MAX_LP 10
297
298
299void add_light(light_patch *&first, long x1, long y1, long x2, long y2,
300                            light_source *who)
301
302  light_patch *last=NULL;
303  for (light_patch *p=first;p;p=p->next)
304  {
305    // first see if light patch we are adding is enclosed entirely by another patch
306    if (x1>=p->x1 && y1>=p->y1 && x2<=p->x2 && y2<=p->y2)
307    {
308      if (p->total==MAX_LP) return ;
309
310      if (x1>p->x1)
311      {
312        first=p->copy(first);
313        first->x2=x1-1;
314      }
315      if (x2<p->x2)
316      {
317        first=p->copy(first);
318        first->x1=x2+1;
319      }
320      if (y1>p->y1)
321      {
322        first=p->copy(first);
323        first->x1=x1;
324        first->x2=x2;
325        first->y2=y1-1;
326      }
327      if (y2<p->y2)
328      {
329        first=p->copy(first);
330        first->x1=x1;
331        first->x2=x2;
332        first->y1=y2+1;
333      }
334      p->x1=x1; p->y1=y1; p->x2=x2; p->y2=y2;
335      p->total++;     
336      p->lights=(light_source **)jrealloc(p->lights,sizeof(light_source *)*p->total,"patch_list");
337      p->lights[p->total-1]=who;
338      return ;
339    }
340
341    // see if the patch completly covers another patch.
342    if (x1<=p->x1 && y1<=p->y1 && x2>=p->x2 && y2>=p->y2)
343    {
344      if (x1<p->x1)
345        add_light(first,x1,y1,p->x1-1,y2,who);
346      if (x2>p->x2)
347        add_light(first,p->x2+1,y1,x2,y2,who);
348      if (y1<p->y1)
349        add_light(first,p->x1,y1,p->x2,p->y1-1,who);
350      if (y2>p->y2)
351        add_light(first,p->x1,p->y2+1,p->x2,y2,who);
352      if (p->total==MAX_LP)  return ;
353      p->total++;     
354      p->lights=(light_source **)jrealloc(p->lights,sizeof(light_source *)*p->total,"patch_list");
355      p->lights[p->total-1]=who;
356      return ;
357    }
358
359    // see if we intersect another rect
360    if (!(x2<p->x1 || y2<p->y1 || x1>p->x2 || y1>p->y2)) 
361    {
362      int ax1,ay1,ax2,ay2;
363      if (x1<p->x1)
364      {
365        add_light(first,x1,max(y1,p->y1),p->x1-1,min(y2,p->y2),who);
366        ax1=p->x1;
367      } else
368        ax1=x1;
369
370      if (x2>p->x2)
371      {
372        add_light(first,p->x2+1,max(y1,p->y1),x2,min(y2,p->y2),who);
373        ax2=p->x2;
374      }
375      else
376        ax2=x2;
377
378      if (y1<p->y1)
379      {       
380        add_light(first,x1,y1,x2,p->y1-1,who);
381        ay1=p->y1;
382      } else
383        ay1=y1;
384
385      if (y2>p->y2)
386      {
387        add_light(first,x1,p->y2+1,x2,y2,who);
388        ay2=p->y2;
389      } else
390        ay2=y2;
391
392       
393      add_light(first,ax1,ay1,ax2,ay2,who);     
394
395      return ;   
396    }
397  }
398}
399 
400light_patch *find_patch(int screenx, int screeny, light_patch *list)
401{
402  for (;list;list=list->next)
403  {
404    if (screenx>=list->x1 && screenx<=list->x2 && screeny>=list->y1 && screeny<=list->y2)
405      return list;
406  }
407  return NULL;
408}
409
410int calc_light_value(long x, long y, light_patch *which)
411{
412  int lv=0;
413  int t=which->total;
414  for (register int i=t-1;i>=0;i--)
415  {   
416    light_source *fn=which->lights[i];
417    if (fn->type==9)
418    {
419      lv=fn->inner_radius;
420      i=0;
421    }
422    else
423    {
424      long dx=abs(fn->x-x)<<fn->xshift;
425      long dy=abs(fn->y-y)<<fn->yshift;
426      long  r2;
427      if (dx<dy)
428        r2=dx+dy-(dx>>1);
429      else r2=dx+dy-(dy>>1);
430   
431      if (r2>=fn->inner_radius)
432      {
433        if (r2<fn->outer_radius)
434        {
435          lv+=((fn->outer_radius-r2)*fn->mul_div)>>16;
436        }
437      } else lv=63;       
438    }
439  }
440  if (lv>63) return 63;
441  else
442    return lv;
443}
444
445
446void reduce_patches(light_patch *f)   // find constant valued patches
447{
448 
449}
450
451light_patch *make_patch_list(int cx1,int cy1,int cx2,int cy2, long screenx, long screeny)
452{
453  light_patch *first=new light_patch(cx1,cy1,cx2,cy2,NULL);
454
455  for (light_source *f=first_light_source;f;f=f->next)   // determine which lights will have effect
456  {
457    long x1=f->x1-screenx,y1=f->y1-screeny,x2=f->x2-screenx,y2=f->y2-screeny;
458    if (x1<cx1) x1=cx1;
459    if (y1<cy1) y1=cy1;
460    if (x2>cx2) x2=cx2;
461    if (y2>cy2) y2=cy2;
462
463    if (x1<=x2 && y1<=y2)
464      add_light(first,x1,y1,x2,y2,f);
465  }
466  reduce_patches(first);
467
468  return first;
469}
470
471void delete_patch_list(light_patch *first)
472{
473  while (first)
474  {
475    light_patch *p=first;
476    first=first->next;
477    delete p;
478  }
479}
480
481
482#ifdef __WATCOMC__
483extern "C" {
484extern long MAP_PUT(long pad, long screen_addr, long remap, long w);
485extern long MAP_PUT2(long dest, long screen_addr, long remap, long w);
486} ;
487#else
488inline long MAP_PUT(long pad, long screen_addr, long remap, long w)
489{ while (w--)
490  {
491    *((uchar *)(screen_addr))=*((uchar *)remap+*((uchar *)screen_addr));
492    screen_addr++;
493  }
494  return screen_addr;
495}
496
497inline long MAP_PUT2(long dest_addr, long screen_addr, long remap, long w)
498{ while (w--)
499  {
500    *((uchar *)(dest_addr))=*((uchar *)remap+*((uchar *)screen_addr));
501    screen_addr++;
502    dest_addr++;
503  }
504  return dest_addr;
505}
506
507#endif
508
509
510inline long calc_lv(light_patch *lp, long sx, long sy)
511{
512  light_source **lon_p=lp->lights;
513  long lv=min_light_level;
514  int light_on;
515  for (light_on=lp->total-1;light_on>=0;light_on--)
516  {
517    light_source *fn=*lon_p;
518    long *dt=&(*lon_p)->type;
519    if (*dt==9)
520    {
521      lv=fn->inner_radius;
522      light_on=0;           
523    } else
524    {
525      dt++;
526      int dx=abs(*dt-sx); dt++;
527      dx<<=*dt;  dt++;
528
529      int dy=abs(*dt-sy); dt++;
530      dy<<=*dt;  dt++;
531
532      int r2;
533      if (dx<dy)
534      r2=dx+dy-(dx>>1);
535      else r2=dx+dy-(dy>>1);
536     
537      if (r2<*dt)
538      {         
539        int v=*dt-r2; dt++;             
540        lv+=v*(*dt)>>16;
541      }
542    }
543    lon_p++;
544  }
545  if (lv>63) return 63;
546  else return lv;
547
548}
549
550
551void light_screen(image *sc, long screenx, long screeny, uchar *light_lookup)
552{
553  int lx_run,ly_run;
554  switch (light_detail)
555  {
556    case HIGH_DETAIL :
557    { lx_run=2; ly_run=1; } break;
558    case MEDIUM_DETAIL :
559    { lx_run=3; ly_run=2; } break;
560    case LOW_DETAIL :
561    { lx_run=4; ly_run=3; } break;
562    case POOR_DETAIL :                   // low detail lighting alread taken care of.
563    return ;
564  }
565
566  short cx1,cy1,cx2,cy2;
567  sc->get_clip(cx1,cy1,cx2,cy2);
568//  sc->add_dirty(cx1,cy1,cx2,cy2);
569  unsigned char *mint=light_lookup+min_light_level*256;
570  screenx-=cx1;
571  screeny-=cy1;
572
573
574  light_patch *first=make_patch_list(cx1,cy1,cx2,cy2,screenx,screeny);
575
576
577  int ytry=(1<<ly_run),xtry=(1<<lx_run);
578  int calcx_mask=(0xefffffff-(xtry-1));
579  int calcy_mask=(0xefffffff-(ytry-1));
580  int scr_w=screen->width();
581
582  for (light_patch *lp=first;lp;lp=lp->next)
583  {
584    register int x2=lp->x2;
585    if (lp->total==0)  // do dark patches really fast.
586    {
587      unsigned char *sl=screen->scan_line(lp->y1)+lp->x1,*dest;
588#ifdef __WATCOMC__
589      if (get_vmode()==19) dest=(uchar *)0xa0000+lp->y1*320+lp->x1;
590      else dest=sl;
591#else
592      dest=sl;
593#endif
594     
595      int y2=lp->y2;
596      for (int y=lp->y1;y<=y2;y++,sl+=scr_w,dest+=scr_w)
597      {
598        int w=lp->x2-lp->x1+1;
599        MAP_PUT2((long)dest,(long)sl,(long)mint,w);
600      }
601    }
602    else
603    {
604      int todoy;
605      int y2=lp->y2;
606
607      int xmask=(xtry-1);
608      int ymask=(ytry-1);
609
610      uchar *yaddr=screen->scan_line(lp->y1)+lp->x1,*dyaddr;
611#ifdef __WATCOMC__
612      if (get_vmode()==19) dyaddr=((uchar *)0xa0000)+lp->y1*320+lp->x1;
613      else dyaddr=yaddr;
614#else
615      dyaddr=yaddr;
616#endif
617
618      for (int y=lp->y1;y<=y2;)
619      {
620        long sy=(screeny+y);
621        if (y+ytry>lp->y2)        // see how many y lines to do for this block
622          todoy=lp->y2-y+1;
623        else todoy=ytry;
624        int maxy=ytry-(sy&ymask);
625        if (todoy>maxy)
626          todoy=maxy;
627       
628        uchar *xaddr=yaddr,*dxaddr=dyaddr;
629        for (register int x=lp->x1;x<=x2;)
630        {
631          long lv=min_light_level;
632          unsigned char *ct;
633          light_source *f;
634          int todox;
635          if (x+xtry>lp->x2)
636            todox=lp->x2-x+1;
637          else todox=xtry;
638          int sx=(screenx+x);
639          int max=xtry-(sx&xmask);
640          if (todox>max)
641            todox=max;
642
643
644          ct=light_lookup+calc_lv(lp,sx,sy)*256;
645          switch (todox)
646          {
647            case 8 :
648            {
649              x+=8;
650              switch (todoy)
651              {
652                case 4 :
653                {
654                  uchar *addr=xaddr,*daddr=dxaddr;
655                  dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
656                  xaddr+=8;
657
658                  addr+=scr_w; daddr+=scr_w;
659                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
660                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
661                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
662                } break;
663                case 3 :
664                {
665                  uchar *addr=xaddr,*daddr=dxaddr;
666                  dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
667                  xaddr+=8;
668
669                  addr+=scr_w; daddr+=scr_w;
670                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);   addr+=scr_w; daddr+=scr_w;
671                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
672
673
674                } break;             
675                case 2 :
676                {
677                  uchar *addr=xaddr,*daddr=dxaddr;
678                  dxaddr=(uchar *)MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
679                  xaddr+=8;
680
681                  addr+=scr_w; daddr+=scr_w;
682                  MAP_PUT2((long)daddr,(long)addr,(long)ct,8);
683
684                } break;
685                case 1 :
686                { dxaddr=(uchar *)MAP_PUT((long)dxaddr,(long)xaddr,(long)ct,8);
687                  xaddr+=8;           
688                } break;
689              }
690            } break;
691/*          case 4 :
692            {
693              x+=4;
694              switch (todoy)
695              {
696                case 4 :
697                {
698                  uchar *addr=xaddr;
699                  xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w; daddr+=scr_w;
700                  MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w; daddr+=scr_w;
701                  MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w; daddr+=scr_w;
702                  MAP_PUT(0,(long)addr,(long)ct,4);
703                } break;
704                case 3 :
705                {
706                  uchar *addr=xaddr;
707                  xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w;  daddr+=scr_w;
708                  MAP_PUT(0,(long)addr,(long)ct,4);                addr+=scr_w;  daddr+=scr_w;
709                  MAP_PUT(0,(long)addr,(long)ct,4);
710                } break;             
711                case 2 :
712                {
713                  uchar *addr=xaddr;
714                  xaddr=(uchar *)MAP_PUT(0,(long)addr,(long)ct,4); addr+=scr_w; daddr+=scr_w;
715                  MAP_PUT(0,(long)addr,(long)ct,4);
716                } break;
717                case 1 : xaddr=(uchar *)MAP_PUT(0,(long)xaddr,(long)ct,4); break;
718              }
719            } break; */
720            default :
721            {
722              x+=todox;
723              if (todoy==1)
724              {
725                dxaddr=(uchar *)MAP_PUT2((long)dxaddr,(long)xaddr,(long)ct,todox);
726                xaddr+=todox;
727              }
728              else
729              {
730                uchar *addr=xaddr,*daddr=dxaddr;
731                dxaddr=(uchar *)MAP_PUT2((long)dxaddr,(long)xaddr,(long)ct,todox);
732                xaddr+=todox;
733
734                addr+=scr_w;
735                daddr+=scr_w;
736
737                int cc=todoy-1;
738                while (cc--)
739                {
740                  MAP_PUT2((long)daddr,(long)addr,(long)ct,todox);
741                  addr+=scr_w;
742                  daddr+=scr_w;
743                }                               
744              }
745            }
746          }
747        }
748         
749        int yadd=scr_w*todoy;
750        yaddr+=yadd;
751        dyaddr+=yadd;
752
753        y+=todoy;
754      }
755    }
756  }
757  while (first)
758  {
759    light_patch *p=first;
760    first=first->next;
761    delete p;
762  }
763}
764
765
766
767
768void add_light_spec(spec_directory *sd, char *level_name)
769{
770  long size=4+4;  // number of lights and minimum light levels
771  for (light_source *f=first_light_source;f;f=f->next)
772    size+=6*4+1;
773  sd->add(new spec_entry(SPEC_LIGHT_LIST,"lights",NULL,size,0)); 
774}
775
776void write_lights(jFILE *fp)
777{
778  int t=0;
779  for (light_source *f=first_light_source;f;f=f->next) t++;
780  fp->write_long(t);
781  fp->write_long(min_light_level);
782  for (f=first_light_source;f;f=f->next)
783  {
784    fp->write_long(f->x);
785    fp->write_long(f->y);
786    fp->write_long(f->xshift);
787    fp->write_long(f->yshift);
788    fp->write_long(f->inner_radius);
789    fp->write_long(f->outer_radius);
790    fp->write_byte(f->type);
791  }
792}
793
794
795int send_lights(net_descriptor *os)
796{
797  packet pk;
798  int t=0;
799  for (light_source *f=first_light_source;f;f=f->next) t++;
800  pk.write_long(t);
801  pk.write_short(min_light_level);
802  if (!os->send(pk)) return 0;
803  for (f=first_light_source;f;f=f->next)
804  {
805    pk.reset();
806    pk.write_long(f->x);
807    pk.write_long(f->y);
808    pk.write_long(f->xshift);
809    pk.write_long(f->yshift);
810    pk.write_long(f->inner_radius);
811    pk.write_long(f->outer_radius);
812    pk.write_long(f->type);
813    if (!os->send(pk)) return 0;   
814  }
815  return 1;
816}
817
818
819void read_lights(spec_directory *sd, jFILE *fp, char *level_name)
820{
821  delete_all_lights();
822  spec_entry *se=sd->find("lights");
823  if (se)
824  {
825    fp->seek(se->offset,SEEK_SET);
826    long t=fp->read_long();
827    min_light_level=fp->read_long();
828    light_source *last;
829    while (t)
830    {
831      t--;
832      long x=fp->read_long();
833      long y=fp->read_long();
834      long xshift=fp->read_long();
835      long yshift=fp->read_long();
836      long ir=fp->read_long();
837      long ora=fp->read_long();
838      long ty=fp->read_byte();
839
840      light_source *p=new light_source(ty,x,y,ir,ora,xshift,yshift,NULL);
841     
842      if (first_light_source)
843        last->next=p;
844      else first_light_source=p;
845      last=p;
846    }
847  }
848}
849
850
851int receive_lights(net_descriptor *os)
852{
853  packet pk;
854  if (!os->get(pk)) { printf("net error : light total\n"); return 0; }
855  long t;
856  if (pk.read((uchar *)&t,4)!=4)
857  { printf("net error : (t) packet incomplete\n"); return 0; }
858  t=lltl(t);
859
860  if (pk.read((uchar *)&min_light_level,2)!=2)
861  { printf("net error : (minl) packet incomplete\n"); return 0; }
862  min_light_level=lstl(min_light_level);
863
864  light_source *last;
865  printf("Reading %d lights\n",t);
866  while (t)
867  {
868    if (!os->get(pk)) {printf("net error : read light\n"); return 0; }
869    t--;
870    long dt[7];
871    if (pk.read((uchar *)dt,7*4)!=7*4) return 0;
872
873
874    light_source *p=new light_source(lltl(dt[6]),
875                                       lltl(dt[0]),lltl(dt[1]),
876                                       lltl(dt[4]),lltl(dt[5]),
877                                       lltl(dt[2]),lltl(dt[3]),NULL);
878     
879    if (first_light_source)
880      last->next=p;
881    else first_light_source=p;
882      last=p;
883  }
884  return 1;
885}
886
887
888
Note: See TracBrowser for help on using the repository browser.