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 <unistd.h>
16 
17 #include "common.h"
18 
19 #include "game.h"
20 
21 #include "view.h"
22 #include "lisp.h"
23 #include "jwindow.h"
24 #include "configuration.h"
25 #include "scroller.h"
26 #include "id.h"
27 #include "dev.h"
28 #include "jrand.h"
29 #include "dprint.h"
30 #include "transp.h"
31 #include "clisp.h"
32 #include "demo.h"
33 #include "sbar.h"
34 #include "nfserver.h"
35 #include "chat.h"
36 
37 #define SHIFT_DOWN_DEFAULT 15
38 #define SHIFT_RIGHT_DEFAULT 0
39 
40 extern int get_key_binding( char const *dir, int i );
41 view *player_list=NULL;
42 int morph_sel_frame_color;
43 
~view()44 view::~view()
45 {
46   if (local_player())
47     sbar.associate(NULL);
48 
49   if (total_weapons)
50   {
51     free(weapons);
52     free(last_weapons);
53   }
54 }
55 
56 
57 extern uint8_t bright_tint[256];
58 
add_ammo(int weapon_type,int total)59 void view::add_ammo(int weapon_type, int total)
60 {
61   if (weapon_type>=total_weapons || weapon_type<0)
62   {
63     printf("weapon out of range\n");
64     return ;
65   }
66   if (weapons[weapon_type]==-1) return ;   // don't have weapon yet, can't give ammo
67 
68   weapons[weapon_type]+=total;
69   if (weapons[weapon_type]<0)
70     weapons[weapon_type]=0;
71 
72   if (weapons[weapon_type]>999)
73     weapons[weapon_type]=999;
74 
75   if (weapon_total(current_weapon)==0 && current_weapon)
76   {
77     suggest.send_weapon_change=1;
78     if (DEFINEDP(symbol_value(l_switch_to_powerful)) && symbol_value(l_switch_to_powerful))
79     {
80       int x=total_weapons-1;
81       while (x>0 && (x==3 || weapons[x]<=0)) x--;
82       suggest.new_weapon=x;
83     } else
84       suggest.new_weapon=0;
85   }
86 
87 }
88 
give_weapon(int type)89 void view::give_weapon(int type)
90 {
91   if (type>=total_weapons || type<0)
92   {
93     printf("weapon out of range\n");
94     return ;
95   }
96   if (weapons[type]==-1)
97   {
98     weapons[type]=0;
99     sbar.need_refresh();
100   }
101 }
102 
weapon_total(int type)103 int view::weapon_total(int type)
104 {
105   if (type>=total_weapons || type<0)
106   {
107     printf("weapon out of range\n");
108     return 0;
109   }
110   if (god) return 100;
111   else if (weapons[type]==-1) return 0;
112   else return weapons[type];
113 }
114 
115 
xoff()116 int32_t view::xoff()
117 {
118   if (focus)
119   {
120     int x=last_x-(cx2-cx1+1)/2+shift_right+pan_x;
121     if (x<0) return 0;
122     else return x;
123   } else return pan_x;
124 }
125 
interpolated_xoff()126 int32_t view::interpolated_xoff()
127 {
128   if (focus)
129   {
130     int x=(last_last_x+last_x)/2-(cx2-cx1+1)/2+shift_right+pan_x;
131     if (x<0) return 0;
132     else return x;
133   } else return pan_x;
134 }
135 
136 
yoff()137 int32_t view::yoff()
138 {
139   if (focus)
140   {
141     int y=last_y-(cy2-cy1+1)/2-shift_down+pan_y;
142     if (y<0) return 0;
143     else return y;
144   } else return pan_y;
145 }
146 
147 
interpolated_yoff()148 int32_t view::interpolated_yoff()
149 {
150   if (focus)
151   {
152     int y=(last_y+last_last_y)/2-(cy2-cy1+1)/2-shift_down+pan_y;
153     if (y<0) return 0;
154     else return y;
155   } else return pan_y;
156 }
157 
158 
update_scroll()159 void view::update_scroll()
160 {
161   if (focus)
162   {
163     last_last_x=last_x;
164     last_last_y=last_y;
165     if (focus->x>last_x)
166     {
167       if (focus->x-last_x>=no_xright)
168         last_x=focus->x-no_xright;
169     } else if (focus->x<last_x)
170     {
171       if (last_x-focus->x>=no_xleft)
172         last_x=focus->x+no_xleft;
173     }
174     if (focus->y>last_y)
175     {
176       if (focus->y-last_y>=no_ybottom)
177         last_y=focus->y-no_ybottom;
178     } else if (focus->y<last_y)
179     {
180       if (last_y-focus->y>=no_ytop)
181         last_y=focus->y+no_ytop;
182     }
183   }
184 }
185 
186 static char cur_user_name[20] = { 0 };
187 
get_login()188 char const *get_login()
189 {
190     if (cur_user_name[0])
191         return cur_user_name;
192 
193 #if defined __CELLOS_LV2__
194     /* FIXME: retrieve login name */
195     return "Player";
196 #else
197     char const *login = getlogin();
198     return login ? login : "unknown";
199 #endif
200 }
201 
set_login(char const * name)202 void set_login(char const *name)
203 {
204     strncpy(cur_user_name, name, 20);
205 }
206 
view(game_object * Focus,view * Next,int number)207 view::view(game_object *Focus, view *Next, int number)
208 {
209   chat_buf[0]=0;
210 
211   draw_solid=-1;
212   no_xleft=0;
213   no_xright=0;
214   no_ytop=0;
215   no_ybottom=0;
216   if (Focus)
217   {
218     last_x=Focus->x;
219     last_y=Focus->y;
220   } else
221   {
222     last_x=last_y=0;
223   }
224 
225   last_last_x=last_x;
226   last_last_y=last_y;
227   last_hp=last_ammo=-1;
228   last_type=-1;
229   tsecrets=secrets=0;
230   tkills=kills=0;
231 
232   reset_keymap();
233 
234   ambient=32;
235   current_weapon=0;
236 
237   strcpy(name,get_login());
238   suggest.send_view=0;
239   suggest.send_weapon_change=0;
240 
241 
242   god=0;
243 
244   player_number=number;
245   cx1=0;
246   cy1=0;
247   cx2=100;
248   cy2=100;
249   focus=Focus;
250   next=Next;
251   shift_down=SHIFT_DOWN_DEFAULT;
252   shift_right=SHIFT_RIGHT_DEFAULT;
253   x_suggestion=0;
254   y_suggestion=0;
255   b1_suggestion=0;
256   b2_suggestion=0;
257   b3_suggestion=0;
258   b4_suggestion=0;
259   pointer_x=0;
260   pointer_y=0;
261 
262   pan_x=0;
263   pan_y=0;
264   last_type=0;
265   freeze_time=0;
266 
267   if (total_weapons)
268   {
269     weapons=(int32_t *)malloc(total_weapons*sizeof(int32_t));
270     last_weapons=(int32_t *)malloc(total_weapons*sizeof(int32_t));
271     memset(weapons,0xff,total_weapons*sizeof(int32_t));   // set all to -1
272     memset(last_weapons,0xff,total_weapons*sizeof(int32_t));   // set all to -1
273   }
274 
275   if (total_weapons)
276     weapons[0]=0;
277   if (local_player())
278     sbar.associate(this);
279   set_tint(number);
280   set_team(-1);
281   sbar.need_refresh();
282 }
283 
x_center()284 int32_t view::x_center()
285 {
286   if (!focus)
287     return (cx1+cx2)/2;
288   else
289     return focus->x;
290 }
291 
y_center()292 int32_t view::y_center()
293 {
294   if (!focus)
295     return (cy1+cy2)/2;
296   else
297     return focus->y;
298 }
299 
draw_character_damage()300 void view::draw_character_damage()
301 {
302   if (focus && drawable())
303   {
304     if (last_hp!=focus->hp()) draw_hp();
305     int i;
306     for (i=0; i<total_weapons; i++)
307       if (weapons[i]!=last_weapons[i])
308       {
309     last_weapons[i]=weapons[i];
310         sbar.draw_ammo(screen,i,weapons[i],current_weapon==i);
311       }
312   }
313 }
314 
315 
316 
make_sync()317 uint16_t make_sync()
318 {
319   uint16_t x=0;
320   if (!current_level) return 0;
321   if (current_level)
322   {
323     view *f=player_list;
324     for (; f; f=f->next)
325     {
326       if (f->focus)
327       {
328     x^=(f->focus->x&0xffff);
329     x^=(f->focus->y&0xffff);
330       }
331     }
332   }
333   x^=rand_on;
334 
335   return x;
336 }
337 
338 
339 
get_input()340 void view::get_input()
341 {
342     int sug_x,sug_y,sug_b1,sug_b2,sug_b3,sug_b4;
343     int32_t sug_px,sug_py;
344 
345 // NOTE:(AK) I have commented this out so we don't use the lisp
346 //        file "input.lsp" to get our key mappings.
347 /*    if( DEFINEDP( symbol_function( l_get_local_input ) ) )
348     {
349         void *ret = ((LSymbol *)l_get_local_input->EvalFunction(NULL);
350         sug_x = lnumber_value( CAR( ret ) );
351         ret = CDR( ret );
352         sug_y = lnumber_value( CAR( ret ) );
353         ret = CDR( ret );
354         if( CAR( ret ) )
355             sug_b1 = 1;
356         else
357             sug_b1 = 0;
358         ret = CDR( ret );
359         if( CAR( ret ) )
360             sug_b2 = 1;
361         else
362             sug_b2 = 0;
363         ret = CDR( ret );
364         int x = lnumber_value( CAR( ret ) );
365         ret = CDR( ret );
366         if( x < 0 )
367             sug_b3 = 1;
368         else
369             sug_b3 = 0;
370         if( x > 0 )
371             sug_b4 = 1;
372         else sug_b4 = 0;
373 
374         int32_t bx = lnumber_value( CAR( ret ) );
375         ret = CDR( ret );
376         int32_t by = lnumber_value( CAR( ret ) );
377         ret = CDR( ret );
378         the_game->mouse_to_game( bx, by, sug_px, sug_py, this );
379 
380     }
381     else*/
382     {
383         get_movement( 0, sug_x, sug_y, sug_b1, sug_b2, sug_b3, sug_b4 );
384         if( focus )
385         {
386             the_game->mouse_to_game( last_demo_mx, last_demo_my, sug_px, sug_py, this );
387             if( last_demo_mbut & 1 )
388                 sug_b2 = 1;
389             if( last_demo_mbut & 2 )
390                 sug_b1 = 1;
391         }
392         else
393             sug_px = sug_py = 0;
394     }
395 
396 #if !defined __CELLOS_LV2__
397     if( view_changed() )
398     {
399         base->packet.write_uint8( SCMD_VIEW_RESIZE );
400         base->packet.write_uint8( player_number );
401         base->packet.write_uint32( suggest.cx1 );
402         base->packet.write_uint32( suggest.cy1 );
403         base->packet.write_uint32( suggest.cx2 );
404         base->packet.write_uint32( suggest.cy2 );
405 
406         base->packet.write_uint32( suggest.pan_x );
407         base->packet.write_uint32( suggest.pan_y );
408         base->packet.write_uint32( suggest.shift_down );
409         base->packet.write_uint32( suggest.shift_right );
410     }
411 
412     if( weapon_changed() )
413     {
414         base->packet.write_uint8( SCMD_WEAPON_CHANGE );
415         base->packet.write_uint8( player_number );
416         base->packet.write_uint32( suggest.new_weapon );
417     }
418 
419     base->packet.write_uint8( SCMD_SET_INPUT );
420     base->packet.write_uint8( player_number );
421 
422     uint8_t mflags = 0;
423     if( sug_x > 0 )
424         mflags |= 1;
425     else if ( sug_x < 0 )
426         mflags |= 2;
427 
428     if( sug_y > 0 )
429         mflags |= 4;
430     else if( sug_y < 0 )
431         mflags |= 8;
432 
433     if( sug_b1 )
434         mflags |= 16;
435     if( sug_b2 )
436         mflags |= 32;
437     if( sug_b3 )
438         mflags |= 64;
439     if( sug_b4 )
440         mflags |= 128;
441 
442     base->packet.write_uint8( mflags );
443     base->packet.write_uint16((uint16_t)((int16_t)sug_px));
444     base->packet.write_uint16((uint16_t)((int16_t)sug_py));
445 #endif
446 }
447 
448 
add_chat_key(int key)449 void view::add_chat_key(int key)  // return string if buf is complete
450 {
451   int len=strlen(chat_buf);
452   if (key==JK_BACKSPACE)
453   {
454     if (len)
455     {
456       chat_buf[len-1]=0;
457       if (local_player() && chat)
458         chat->draw_user(chat_buf);
459     }
460   } else if (key!=JK_ENTER)
461   {
462     chat_buf[len]=key;
463     chat_buf[len+1]=0;
464     if (local_player() && chat)
465       chat->draw_user(chat_buf);
466   }
467 
468   if (len>38 || key==JK_ENTER)
469   {
470     if (DEFINEDP(l_chat_input->GetFunction()))
471     {
472       game_object *o=current_object;
473       current_object=focus;
474 
475       void *m=mark_heap(TMP_SPACE);
476       void *list=NULL;
477       push_onto_list(LString::Create(chat_buf),list);
478       ((LSymbol *)l_chat_input)->EvalFunction(list);
479       restore_heap(m,TMP_SPACE);
480 
481       current_object=o;
482 
483     } else
484     {
485       if (chat)
486         chat->put_all(chat_buf);
487     }
488     chat_buf[0]=0;
489     if (local_player() && chat)
490       chat->draw_user(chat_buf);
491   }
492 }
493 
process_input(char cmd,uint8_t * & pk)494 int view::process_input(char cmd, uint8_t *&pk)   // return 0 if something went wrong
495 {
496 #if !defined __CELLOS_LV2__
497   switch (cmd)
498   {
499     case SCMD_CHAT_KEYPRESS :
500     {
501       add_chat_key(*(pk++));
502     } break;
503     case SCMD_VIEW_RESIZE :
504     {
505       int32_t x[8];
506       memcpy(x,pk,8*4);  pk+=8*4;
507       cx1=lltl(x[0]);
508       cy1=lltl(x[1]);
509       cx2=lltl(x[2]);
510       cy2=lltl(x[3]);
511 
512       pan_x=lltl(x[4]);
513       pan_y=lltl(x[5]);
514       shift_down=lltl(x[6]);
515       shift_right=lltl(x[7]);
516       if (small_render)
517       {
518         small_render->Scale(vec2i(cx2 - cx1 + 1, cy2 - cy1 + 1));
519       }
520 
521       suggest.send_view=0;
522       if (local_player())
523         the_game->draw();
524       return 1;
525     }
526     case SCMD_WEAPON_CHANGE :
527     {
528       int32_t x;
529       memcpy(&x,pk,4);  pk+=4;
530       current_weapon=lltl(x);
531 
532       if (local_player())
533         sbar.need_refresh();
534       suggest.send_weapon_change=0;
535       return 1;
536     } break;
537 
538     case SCMD_SET_INPUT :
539     {
540       uint8_t x=*(pk++);
541 
542       if (x&1) x_suggestion=1;
543       else if (x&2) x_suggestion=-1;
544       else x_suggestion=0;
545 
546       if (x&4) y_suggestion=1;
547       else if (x&8) y_suggestion=-1;
548       else y_suggestion=0;
549 
550       if (x&16) b1_suggestion=1; else b1_suggestion=0;
551       if (x&32) b2_suggestion=1; else b2_suggestion=0;
552       if (x&64) b3_suggestion=1; else b3_suggestion=0;
553       if (x&128) b4_suggestion=1; else b4_suggestion=0;
554 
555       uint16_t p[2];
556       memcpy(p,pk,2*2);  pk+=2*2;
557 
558       pointer_x=(int16_t)(lstl(p[0]));
559       pointer_y=(int16_t)(lstl(p[1]));
560 
561       return 1;
562     } break;
563     case SCMD_KEYPRESS : set_key_down(*(pk++),1); break;
564     case SCMD_EXT_KEYPRESS : set_key_down(*(pk++)+256,1); break;
565     case SCMD_KEYRELEASE : set_key_down(*(pk++),0); break;
566     case SCMD_EXT_KEYRELEASE : set_key_down(*(pk++)+256,0); break;
567   }
568 #endif
569   return 1;
570 }
571 
local_player()572 int view::local_player()
573 {
574 #if defined __CELLOS_LV2__
575   return 1;
576 #else
577   return player_number==client_number();
578 #endif
579 }
580 
next_weapon()581 void view::next_weapon()
582 {
583   int c=current_weapon;
584 
585   while (c<total_weapons-1)
586   {
587     c++;
588     if (weapon_total(c)>0)
589     {
590       suggest.send_weapon_change=1;
591       suggest.new_weapon=c;
592       return ;
593     }
594   }
595 
596   c=0;
597   while (c!=current_weapon)
598   {
599     if (weapon_total(c)>0)
600     {
601       suggest.send_weapon_change=1;
602       suggest.new_weapon=c;
603       return ;
604     }
605     c++;
606   }
607 }
608 
last_weapon()609 void view::last_weapon()
610 {
611 
612   int c=current_weapon;
613 
614   while (c>=1)
615   {
616     c--;
617     if (weapon_total(c)>0 || c==0)
618     {
619       suggest.send_weapon_change=1;
620       suggest.new_weapon=c;
621       return ;
622     }
623   }
624 
625   c=total_weapons-1;
626   while (c!=current_weapon)
627   {
628     if (weapon_total(c)>0 || c==0)
629     {
630       suggest.send_weapon_change=1;
631       suggest.new_weapon=c;
632       return ;
633     }
634     c--;
635   }
636 
637 }
638 
handle_event(event & ev)639 int view::handle_event(event &ev)
640 {
641     if( ev.type == EV_KEY )
642     {
643         if( ev.key == (int)',' )
644         {
645             if( total_weapons )
646             {
647                 last_weapon();
648             }
649             return 1;
650         }
651         else if( ev.key == (int)'.' )
652         {
653             if( total_weapons )
654             {
655                 next_weapon();
656             }
657             return 1;
658         }
659         else if( ev.key == get_key_binding( "b3", 0 ) )
660         {
661             if( total_weapons )
662             {
663                 last_weapon();
664             }
665             return 1;
666         }
667         else if( ev.key == get_key_binding( "b4", 0 ) )
668         {
669             if( total_weapons )
670             {
671                 next_weapon();
672             }
673             return 1;
674         }
675 
676         switch( ev.key )
677         {
678             case '1':
679             case '2':
680             case '3':
681             case '4':
682             case '5':
683             case '6':
684             case '7':
685             {
686                 if((( dev & EDIT_MODE ) == 0 ) && ( weapon_total( ev.key - '1' ) > 0 ))
687                 {
688                     suggest.send_weapon_change = 1;
689                     suggest.new_weapon=ev.key - '1';
690                 }
691             } break;
692 
693             case JK_HOME:
694             case JK_CTRL_L:
695             case JK_CTRL_R:
696             {
697                 if( total_weapons )
698                 {
699                     last_weapon();
700                 }
701                 return 1;
702             } break;
703             case JK_PAGEUP:
704             case JK_INSERT:
705             {
706                 if( total_weapons )
707                 {
708                     next_weapon();
709                 }
710                 return 1;
711             } break;
712         }
713     }
714     return 0;
715 }
716 
draw_hp()717 void view::draw_hp()
718 {
719     if (focus)
720     {
721         int h = focus->hp();
722         last_hp=h;
723         sbar.draw_health( screen, focus->hp() );
724     }
725     else
726     {
727         sbar.draw_health( screen, 0 );
728     }
729 }
730 
drawable()731 int view::drawable()
732 {
733     return local_player();
734 }
735 
736 
recalc_local_view_space()737 void recalc_local_view_space()   // calculates view areas for local players, should be called
738                                  // when adding or deleting local players
739 {
740   if (screen)
741   {
742     int t=total_local_players();
743     if (!t) return ;
744 
745     int Xres=small_render ? xres/2 : xres;
746     int Yres=small_render ? yres/2 : yres;
747 
748     int h=Yres/t;
749     int w=h*320/200,y=5;
750     if (w<300) w=300;
751 
752     for (view *f=player_list; f; f=f->next)
753     {
754       if (f->local_player())
755       {
756     f->suggest.cx1=Xres/2-w/2;
757     f->suggest.cx2=Xres/2+w/2;
758     if (f->suggest.cx1<2) f->suggest.cx1=2;
759     if (f->suggest.cx2>Xres-2) f->suggest.cx2=Xres-2;
760 
761     f->suggest.cy1=y;
762     f->suggest.cy2=h-(total_weapons ? 33 : 0);
763 
764     f->suggest.shift_down=f->shift_down;
765     f->suggest.shift_right=f->shift_right;
766     f->suggest.pan_x=f->pan_x;
767     f->suggest.pan_y=f->pan_y;
768     f->suggest.send_view=1;
769 
770     if (!player_list->next)
771     {
772       f->cx1=f->suggest.cx1;
773       f->cy1=f->suggest.cy1;
774       f->cx2=f->suggest.cx2;
775       f->cy2=f->suggest.cy2;
776       f->suggest.send_view=0;
777     }
778     y+=h;
779       }
780     }
781   }
782 
783 }
784 
785 
set_local_players(int total)786 void set_local_players(int total)
787 {
788   int rdw=0;
789   if (total<1) return ;
790 
791   view *last=NULL;
792   for (view *f=player_list; f; f=f->next)
793   {
794     if (total && f->local_player())
795       total--;
796     else if (!total && f->local_player())  // too many local players, delete this one
797     {
798       view *n=last->next;
799       while (n && !n->local_player()) n=n->next;  // find next local player
800 
801       if (last)
802         last->next=n;
803       else
804       {
805     if (n)    // make sure we have at least one local player
806           player_list=n;
807       }
808       last=f;
809       rdw=1;
810     }
811   }
812 
813   while (total)   // see if we need to add new players
814   {
815     game_object *o=create(current_start_type,50,50);
816     view *v;
817     if (!player_list)
818     {
819       player_list=new view(o,NULL,0);
820       v=player_list;
821     }
822     else
823     {
824       view *f=player_list;
825       for (; f && f->next; f=f->next);
826       f->next=new view(o,NULL,f->player_number+1);
827       v=f->next;
828     }
829     v->cx1=320/2-155; v->cy1=200/2-95; v->cx2=320/2+155; v->cy2=200/2+(total_weapons ? 60 : 95);
830     v->focus->set_controller(v);
831     total--;
832     rdw=1;
833   }
834   if (rdw)
835     recalc_local_view_space();
836 }
837 
838 
total_local_players()839 int total_local_players()
840 {
841   int t=0;
842   for (view *f=player_list; f; f=f->next)
843     if (f->local_player()) t++;
844   return t;
845 }
846 
847 
resize_view(int32_t Cx1,int32_t Cy1,int32_t Cx2,int32_t Cy2)848 void view::resize_view(int32_t Cx1, int32_t Cy1, int32_t Cx2, int32_t Cy2)
849 {
850   if (cx1!=Cx1 || cx2!=Cx2 || cy1!=Cy1 || cy2!=Cy2)
851   {
852     cx1=Cx1; cy1=Cy1;
853     cx2=Cx2; cy2=Cy2;
854     if (playing_state(the_game->state) && local_player())
855       the_game->draw(0);
856   }
857 }
858 
859 
set_input(int cx,int cy,int b1,int b2,int b3,int b4,int px,int py)860 void view::set_input(int cx, int cy, int b1, int b2, int b3, int b4, int px, int py)
861 {
862     x_suggestion=cx;
863     y_suggestion=cy;
864     b1_suggestion=b1;
865     b2_suggestion=b2;
866     b3_suggestion=b3;
867     b4_suggestion=b4;
868     pointer_x=px;
869     pointer_y=py;
870 }
871 
872 
873 
reset_player()874 void view::reset_player()
875 {
876   if (focus)
877   {
878 
879     game_object *start=current_level ? current_level->get_random_start(320,focus->controller()) : 0;
880     focus->defaults();
881     if (start)
882     {
883       focus->x=start->x;
884       focus->y=start->y;
885       dprintf("reset player position to %d %d\n",start->x,start->y);
886     }
887     focus->set_state(stopped);
888     focus->set_tint(_tint);
889     focus->set_team(_team);
890     memset(weapons,0xff,total_weapons*sizeof(int32_t));
891     memset(last_weapons,0xff,total_weapons*sizeof(int32_t));
892 
893     shift_down=SHIFT_DOWN_DEFAULT;
894     shift_right=SHIFT_RIGHT_DEFAULT;
895 
896     if (total_weapons)
897       weapons[0]=0;  // give him the first weapon
898     current_weapon=0;
899 
900     memset(focus->lvars,0,figures[focus->otype]->tv*4);
901     focus->set_aistate(0);
902     if (figures[focus->otype]->get_fun(OFUN_CONSTRUCTOR))
903     {
904       game_object *o=current_object;
905       current_object=focus;
906       ((LSymbol *)figures[focus->otype]->get_fun(OFUN_CONSTRUCTOR))->EvalUserFunction(NULL);
907       current_object=o;
908     }
909     sbar.redraw(screen);
910 
911     int i;
912     for (i=0; i<focus->total_objects(); i++)   // reset the vars for the attached objects
913     {
914       game_object *o=focus->get_object(i);
915       memset(o->lvars,0,figures[o->otype]->tv*4);
916     }
917 
918   }
919 }
920 
921 
922 
923 
924 
make_player_onodes(int player_num)925 object_node *make_player_onodes(int player_num)
926 {
927   object_node *first=NULL,*last=NULL;
928   for (view *o=player_list; o; o=o->next)
929   {
930     if (o->focus && (player_num==-1 || o->player_number==player_num))
931     {
932       if (!object_to_number_in_list(o->focus,first))
933       {
934     object_node *q=new object_node(o->focus,NULL);
935     if (first)
936       last->next=q;
937     else first=q;
938     last=q;
939       }
940       for (int i=0; i<o->focus->total_objects(); i++)
941       {
942     game_object *p=o->focus->get_object(i);
943 
944     if (!object_to_number_in_list(p,first))
945     {
946       object_node *q=new object_node(p,NULL);
947       if (first)
948         last->next=q;
949       else first=q;
950       last=q;
951     }
952       }
953     }
954   }
955   return first;
956 }
957 
958 
959 
960 
961 enum { V_CX1, V_CY1, V_CX2, V_CY2,
962        V_SHIFT_DOWN, V_SHIFT_RIGHT,
963        V_GOD,
964        V_PLAYER_NUMBER,
965        V_DRAW_SOLID,
966        V_LIVES,
967        V_CURRENT_WEAPON,
968        V_X_SUGGESTION, V_Y_SUGGESTION, V_B1_SUGGESTION, V_B2_SUGGESTION, V_B3_SUGGESTION, V_B4_SUGGESTION,
969        V_PAN_X, V_PAN_Y,
970        V_NO_XLEFT, V_NO_XRIGHT, V_NO_YTOP, V_NO_YBOTTOM,
971        V_LAST_X, V_LAST_Y, V_LAST_LEFT, V_LAST_RIGHT, V_LAST_UP, V_LAST_DOWN,
972        V_LAST_B1, V_LAST_B2, V_LAST_B3, V_LAST_B4,
973        V_LAST_HP,
974        V_SECRETS, V_KILLS, V_TSECRETS, V_TKILLS,
975        V_AMBIENT,
976        V_POINTER_X, V_POINTER_Y,
977        V_LAST_LAST_X, V_LAST_LAST_Y,
978        V_FREEZE_TIME };
979 
980 #define TVV (V_FREEZE_TIME+1)
981 
982 static char const *vv_names[TVV] =
983 {
984     "view.cx1",  "view.cy1",  "view.cx2",  "view.cy2",
985     "view.shift_down",  "view.shift_right",
986     "view.god",
987     "view.player_number",
988     "view.draw_solid",
989     "view.lives",
990     "view.current_weapon",
991     "view.x_suggestion",  "view.y_suggestion",
992     "view.b1_suggestion",  "view.b2_suggestion",  "view.b3_suggestion",  "view.b4_suggestion",
993     "view.pan_x",  "view.pan_y",
994     "view.no_xleft",  "view.no_xright",  "view.no_ytop",  "view.no_ybottom",
995     "view.last_x",  "view.last_y",  "view.last_left",  "view.last_right",  "view.last_up",  "view.last_down",
996     "view.last_b1",  "view.last_b2",  "view.last_b3",  "view.last_b4",
997     "view.last_hp",
998     "view.secrets",  "view.kills",  "view.tsecrets",  "view.tkills",
999     "view.ambient",
1000     "view.pointer_x",  "view.pointer_y",
1001     "view.last_last_x",  "view.last_last_y",
1002     "view.freeze_time"
1003 };
1004 
1005 
total_view_vars()1006 int total_view_vars()
1007 { return TVV;
1008 }
1009 
get_view_var_name(int num)1010 char const *get_view_var_name(int num)
1011 { return vv_names[num]; }
1012 
get_view_var_value(int num)1013 int32_t view::get_view_var_value(int num)
1014 {
1015   switch (num)
1016   {
1017     case V_CX1 : return cx1; break;
1018     case V_CY1 : return cy1; break;
1019     case V_CX2 : return cx2; break;
1020     case V_CY2 : return cy2; break;
1021     case V_SHIFT_DOWN : return shift_down; break;
1022     case V_SHIFT_RIGHT : return shift_right; break;
1023     case V_GOD : return god; break;
1024     case V_PLAYER_NUMBER : return player_number; break;
1025 
1026     case V_DRAW_SOLID : return draw_solid; break;
1027     case V_CURRENT_WEAPON : return current_weapon; break;
1028     case V_X_SUGGESTION : return x_suggestion; break;
1029     case V_Y_SUGGESTION : return y_suggestion; break;
1030     case V_B1_SUGGESTION : return b1_suggestion; break;
1031     case V_B2_SUGGESTION : return b2_suggestion; break;
1032     case V_B3_SUGGESTION : return b3_suggestion; break;
1033     case V_B4_SUGGESTION : return b4_suggestion; break;
1034 
1035     case V_PAN_X : return pan_x; break;
1036     case V_PAN_Y : return pan_y; break;
1037     case V_NO_XLEFT : return no_xleft; break;
1038     case V_NO_XRIGHT : return no_xright; break;
1039     case V_NO_YTOP : return no_ytop; break;
1040     case V_NO_YBOTTOM : return no_ybottom; break;
1041     case V_LAST_X : return last_x; break;
1042     case V_LAST_Y : return last_y; break;
1043     case V_LAST_LEFT : return last_left; break;
1044     case V_LAST_RIGHT : return last_right; break;
1045     case V_LAST_UP : return last_up; break;
1046     case V_LAST_DOWN : return last_down; break;
1047     case V_LAST_B1 : return last_b1; break;
1048     case V_LAST_B2 : return last_b2; break;
1049     case V_LAST_B3 : return last_b3; break;
1050     case V_LAST_B4 : return last_b4; break;
1051     case V_LAST_HP : return last_hp; break;
1052     case V_SECRETS : return secrets; break;
1053     case V_KILLS : return kills; break;
1054     case V_TSECRETS : return tsecrets; break;
1055     case V_TKILLS : return tkills; break;
1056     case V_AMBIENT : return ambient; break;
1057     case V_POINTER_X : return pointer_x; break;
1058     case V_POINTER_Y : return pointer_y; break;
1059     case V_LAST_LAST_X : return last_last_x; break;
1060     case V_LAST_LAST_Y : return last_last_y; break;
1061     case V_FREEZE_TIME : return freeze_time; break;
1062   }
1063   return 0;
1064 }
1065 
1066 
1067 
set_view_var_value(int num,int32_t x)1068 int32_t view::set_view_var_value(int num, int32_t x)
1069 {
1070   switch (num)
1071   {
1072     case V_CX1 : cx1=x; break;
1073     case V_CY1 : cy1=x; break;
1074     case V_CX2 : cx2=x; break;
1075     case V_CY2 : cy2=x; break;
1076     case V_SHIFT_DOWN : shift_down=x; break;
1077     case V_SHIFT_RIGHT : shift_right=x; break;
1078     case V_GOD : god=x; break;
1079     case V_PLAYER_NUMBER : { player_number=x; if (local_player()) sbar.associate(this); }  break;
1080 
1081     case V_DRAW_SOLID : draw_solid=x; break;
1082     case V_CURRENT_WEAPON : { current_weapon=x; sbar.need_refresh(); } break;
1083     case V_X_SUGGESTION : x_suggestion=x; break;
1084     case V_Y_SUGGESTION : y_suggestion=x; break;
1085     case V_B1_SUGGESTION : b1_suggestion=x; break;
1086     case V_B2_SUGGESTION : b2_suggestion=x; break;
1087     case V_B3_SUGGESTION : b3_suggestion=x; break;
1088     case V_B4_SUGGESTION : b4_suggestion=x; break;
1089 
1090     case V_PAN_X : pan_x=x; break;
1091     case V_PAN_Y : pan_y=x; break;
1092     case V_NO_XLEFT : no_xleft=x; break;
1093     case V_NO_XRIGHT : no_xright=x; break;
1094     case V_NO_YTOP : no_ytop=x; break;
1095     case V_NO_YBOTTOM : no_ybottom=x; break;
1096     case V_LAST_X : last_x=x; break;
1097     case V_LAST_Y : last_y=x; break;
1098     case V_LAST_LEFT : last_left=x; break;
1099     case V_LAST_RIGHT : last_right=x; break;
1100     case V_LAST_UP : last_up=x; break;
1101     case V_LAST_DOWN : last_down=x; break;
1102     case V_LAST_B1 : last_b1=x; break;
1103     case V_LAST_B2 : last_b2=x; break;
1104     case V_LAST_B3 : last_b3=x; break;
1105     case V_LAST_B4 : last_b4=x; break;
1106 
1107     case V_LAST_HP : last_hp=x; break;
1108     case V_SECRETS : secrets=x; break;
1109     case V_KILLS : kills=x; break;
1110     case V_TSECRETS : tsecrets=x; break;
1111     case V_TKILLS : tkills=x; break;
1112     case V_AMBIENT : ambient=x; break;
1113     case V_POINTER_X : pointer_x=x; break;
1114     case V_POINTER_Y : pointer_y=x; break;
1115     case V_LAST_LAST_X : last_last_x=x; break;
1116     case V_LAST_LAST_Y : last_last_y=x; break;
1117     case V_FREEZE_TIME : freeze_time=x; break;
1118   }
1119   return 1;
1120 }
1121 
1122 
configure_for_area(area_controller * a)1123 void view::configure_for_area(area_controller *a)
1124 {
1125   if (a->ambient>=0 && a->ambient!=ambient)
1126   {
1127     if (ambient>a->ambient)
1128     {
1129       ambient-=a->ambient_speed;
1130       if (ambient<a->ambient)
1131         ambient=a->ambient;
1132     }
1133     else
1134     {
1135       ambient+=a->ambient_speed;
1136       if (ambient>a->ambient)
1137         ambient=a->ambient;
1138     }
1139   }
1140 
1141   if (!view_shift_disabled)
1142   {
1143     if (a->view_xoff!=pan_x)
1144     {
1145       if (pan_x>a->view_xoff)
1146       {
1147     pan_x-=a->view_xoff_speed;
1148     if (pan_x<a->view_xoff)
1149         pan_x=a->view_xoff;
1150       }
1151       else
1152       {
1153     pan_x+=a->view_xoff_speed;
1154     if (pan_x>a->view_xoff)
1155         pan_x=a->view_xoff;
1156       }
1157     }
1158 
1159     if (a->view_yoff!=pan_y)
1160     {
1161       if (pan_y>a->view_yoff)
1162       {
1163     pan_y-=a->view_yoff_speed;
1164     if (pan_y<a->view_yoff)
1165         pan_y=a->view_yoff;
1166       }
1167       else
1168       {
1169     pan_y+=a->view_yoff_speed;
1170     if (pan_y>a->view_yoff)
1171         pan_y=a->view_yoff;
1172       }
1173     }
1174   }
1175 }
1176 
1177 
process_packet_commands(uint8_t * pk,int size)1178 void process_packet_commands(uint8_t *pk, int size)
1179 {
1180 #if !defined __CELLOS_LV2__
1181   int32_t sync_uint16=-1;
1182 
1183   if (!size) return ;
1184   pk[size]=SCMD_END_OF_PACKET;
1185 
1186   uint8_t cmd;
1187   int already_reloaded=0;
1188 
1189 
1190   do
1191   {
1192     cmd=*(pk++);
1193     switch (cmd)
1194     {
1195       case SCMD_WEAPON_CHANGE :
1196       case SCMD_SET_INPUT :
1197       case SCMD_VIEW_RESIZE :
1198       case SCMD_KEYPRESS :
1199       case SCMD_KEYRELEASE :
1200       case SCMD_EXT_KEYPRESS :
1201       case SCMD_EXT_KEYRELEASE :
1202       case SCMD_CHAT_KEYPRESS :
1203       {
1204     uint8_t player_num=*(pk++);
1205 
1206     view *v=player_list;
1207     for (; v && v->player_number!=player_num; v=v->next);
1208     if (v)
1209     {
1210       if (v->player_number==player_num)
1211       v->process_input(cmd,pk);
1212     }
1213     else
1214     {
1215       dprintf("Evil error : bad player number in packet\n");
1216       return ;
1217     }
1218       } break;
1219       case SCMD_RELOAD :
1220       {
1221     if (!already_reloaded)
1222     {
1223       net_reload();
1224       already_reloaded=1;
1225     }
1226       } break;
1227 
1228       case SCMD_SYNC :
1229       {
1230     uint16_t x;
1231     memcpy(&x,pk,2);  pk+=2;
1232     x=lstl(x);
1233     if (demo_man.current_state()==demo_manager::PLAYING)
1234     sync_uint16=make_sync();
1235 
1236     if (sync_uint16==-1)
1237     sync_uint16=x;
1238     else if (x!=sync_uint16 && !already_reloaded)
1239     {
1240       dprintf("out of sync %d (packet=%d, calced=%d)\n",current_level->tick_counter(),x,sync_uint16);
1241       if (demo_man.current_state()==demo_manager::NORMAL)
1242         net_reload();
1243       already_reloaded=1;
1244     }
1245       } break;
1246       case SCMD_DELETE_CLIENT :
1247       {
1248     uint8_t player_num=*(pk++);
1249     view *v=player_list,*last=NULL;
1250     for (; v && v->player_number!=player_num; v=v->next)
1251     last=v;
1252     if (!v)
1253     dprintf("evil : delete client %d, but no such client\n");
1254     else
1255     {
1256 
1257       // make a list of all objects associated with this player
1258       object_node *on=make_player_onodes(player_num);
1259       while (on)
1260       {
1261         current_level->delete_object(on->me);
1262         object_node *last=on;
1263         on=on->next;
1264         delete last;
1265       }
1266 
1267       v->focus=NULL;
1268       if (last)
1269       last->next=v->next;
1270       else player_list=player_list->next;
1271 
1272       delete v;
1273     }
1274       } break;
1275       default :
1276       dprintf("Unknown net command %d\n",cmd);
1277 
1278     }
1279   } while (cmd!=SCMD_END_OF_PACKET);
1280 #endif
1281 }
1282 
set_tint(int tint)1283 void view::set_tint(int tint)
1284 {
1285     if(tint < 0)
1286         tint = 0;
1287     _tint = tint;
1288     focus->set_tint(tint);
1289 }
1290 
get_tint()1291 int view::get_tint()
1292 {
1293     return _tint;
1294 }
1295 
set_team(int team)1296 void view::set_team(int team)
1297 {
1298     if(team < 0)
1299         team = 0;
1300     _team = team;
1301     focus->set_team(team);
1302 }
1303 
get_team()1304 int view::get_team()
1305 {
1306     return _team;
1307 }
1308 
1309