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

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

style: remove trailing spaces, fix copyright statements.

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