source: abuse/trunk/src/newlight.cpp @ 2

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