summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/wolf3d/wl_agent.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2019-07-07 22:00:20 -0400
committerFranklin Wei <git@fwei.tk>2019-07-09 11:20:55 -0400
commit3f59fc8b771625aca9c3aefe03cf1038d8461963 (patch)
treee0623a323613baa0b0993411b38bcaed144b27ed /apps/plugins/sdl/progs/wolf3d/wl_agent.c
parent439a0d1d91fa040d261fc39b87278bc9f5391dcc (diff)
downloadrockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.tar.gz
rockbox-3f59fc8b771625aca9c3aefe03cf1038d8461963.zip
Wolfenstein 3-D!
This is a port of Wolf4SDL, which is derived from the original id software source release. The port runs on top of the SDL plugin runtime and is loaded as an overlay. Licensing of the game code is not an issue, as discussed below (essentially, the Debian project treats Wolf4SDL as GPLv2, with an email from John Carmack backing it up): http://forums.rockbox.org/index.php?topic=52872 Included is a copy of MAME's Yamaha OPL sound chip emulator (fmopl_gpl.c). This file was not part of the original Wolf4SDL source (which includes a non-GPL'd version), but was rather rebased from from a later MAME source which had been relicensed to GPLv2. Change-Id: I64c2ba035e0be7e2f49252f40640641416613439
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/wl_agent.c')
-rw-r--r--apps/plugins/sdl/progs/wolf3d/wl_agent.c1499
1 files changed, 1499 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/wl_agent.c b/apps/plugins/sdl/progs/wolf3d/wl_agent.c
new file mode 100644
index 0000000000..6b9b124a64
--- /dev/null
+++ b/apps/plugins/sdl/progs/wolf3d/wl_agent.c
@@ -0,0 +1,1499 @@
1// WL_AGENT.C
2
3#include "wl_def.h"
4#pragma hdrstop
5
6/*
7=============================================================================
8
9 LOCAL CONSTANTS
10
11=============================================================================
12*/
13
14#define MAXMOUSETURN 10
15
16
17#define MOVESCALE 150l
18#define BACKMOVESCALE 100l
19#define ANGLESCALE 20
20
21/*
22=============================================================================
23
24 GLOBAL VARIABLES
25
26=============================================================================
27*/
28
29
30
31//
32// player state info
33//
34int32_t thrustspeed;
35
36word plux,pluy; // player coordinates scaled to unsigned
37
38short anglefrac;
39
40objtype *LastAttacker;
41
42/*
43=============================================================================
44
45 LOCAL VARIABLES
46
47=============================================================================
48*/
49
50
51void T_Player (objtype *ob);
52void T_Attack (objtype *ob);
53
54statetype s_player = {false,0,0,(statefunc) T_Player,NULL,NULL};
55statetype s_attack = {false,0,0,(statefunc) T_Attack,NULL,NULL};
56
57struct atkinf
58{
59 int8_t tics,attack,frame; // attack is 1 for gun, 2 for knife
60} attackinfo[4][14] =
61{
62 { {6,0,1},{6,2,2},{6,0,3},{6,-1,4} },
63 { {6,0,1},{6,1,2},{6,0,3},{6,-1,4} },
64 { {6,0,1},{6,1,2},{6,3,3},{6,-1,4} },
65 { {6,0,1},{6,1,2},{6,4,3},{6,-1,4} },
66};
67
68//===========================================================================
69
70//----------
71
72void Attack (void);
73void Use (void);
74void Search (objtype *ob);
75void SelectWeapon (void);
76void SelectItem (void);
77
78//----------
79
80boolean TryMove (objtype *ob);
81void T_Player (objtype *ob);
82
83void ClipMove (objtype *ob, int32_t xmove, int32_t ymove);
84
85/*
86=============================================================================
87
88 CONTROL STUFF
89
90=============================================================================
91*/
92
93/*
94======================
95=
96= CheckWeaponChange
97=
98= Keys 1-4 change weapons
99=
100======================
101*/
102
103void CheckWeaponChange (void)
104{
105 int newWeapon = -1;
106
107 if (!gamestate.ammo) // must use knife with no ammo
108 return;
109
110 if(buttonstate[bt_nextweapon] && !buttonheld[bt_nextweapon])
111 {
112 newWeapon = gamestate.weapon + 1;
113 if(newWeapon > gamestate.bestweapon) newWeapon = 0;
114 }
115 else if(buttonstate[bt_prevweapon] && !buttonheld[bt_prevweapon])
116 {
117 newWeapon = gamestate.weapon - 1;
118 if(newWeapon < 0) newWeapon = gamestate.bestweapon;
119 }
120 else
121 {
122 for(int i = wp_knife; i <= gamestate.bestweapon; i++)
123 {
124 if (buttonstate[bt_readyknife + i - wp_knife])
125 {
126 newWeapon = i;
127 break;
128 }
129 }
130 }
131
132 if(newWeapon != -1)
133 {
134 gamestate.weapon = gamestate.chosenweapon = (weapontype) newWeapon;
135 DrawWeapon();
136 }
137}
138
139
140/*
141=======================
142=
143= ControlMovement
144=
145= Takes controlx,controly, and buttonstate[bt_strafe]
146=
147= Changes the player's angle and position
148=
149= There is an angle hack because when going 70 fps, the roundoff becomes
150= significant
151=
152=======================
153*/
154
155void ControlMovement (objtype *ob)
156{
157 int32_t oldx,oldy;
158 int angle;
159 int angleunits;
160
161 thrustspeed = 0;
162
163 oldx = player->x;
164 oldy = player->y;
165
166 if(buttonstate[bt_strafeleft])
167 {
168 angle = ob->angle + ANGLES/4;
169 if(angle >= ANGLES)
170 angle -= ANGLES;
171 if(buttonstate[bt_run])
172 Thrust(angle, RUNMOVE * MOVESCALE * tics);
173 else
174 Thrust(angle, BASEMOVE * MOVESCALE * tics);
175 }
176
177 if(buttonstate[bt_straferight])
178 {
179 angle = ob->angle - ANGLES/4;
180 if(angle < 0)
181 angle += ANGLES;
182 if(buttonstate[bt_run])
183 Thrust(angle, RUNMOVE * MOVESCALE * tics );
184 else
185 Thrust(angle, BASEMOVE * MOVESCALE * tics);
186 }
187
188 //
189 // side to side move
190 //
191 if (buttonstate[bt_strafe])
192 {
193 //
194 // strafing
195 //
196 //
197 if (controlx > 0)
198 {
199 angle = ob->angle - ANGLES/4;
200 if (angle < 0)
201 angle += ANGLES;
202 Thrust (angle,controlx*MOVESCALE); // move to left
203 }
204 else if (controlx < 0)
205 {
206 angle = ob->angle + ANGLES/4;
207 if (angle >= ANGLES)
208 angle -= ANGLES;
209 Thrust (angle,-controlx*MOVESCALE); // move to right
210 }
211 }
212 else
213 {
214 //
215 // not strafing
216 //
217 anglefrac += controlx;
218 angleunits = anglefrac/ANGLESCALE;
219 anglefrac -= angleunits*ANGLESCALE;
220 ob->angle -= angleunits;
221
222 if (ob->angle >= ANGLES)
223 ob->angle -= ANGLES;
224 if (ob->angle < 0)
225 ob->angle += ANGLES;
226
227 }
228
229 //
230 // forward/backwards move
231 //
232 if (controly < 0)
233 {
234 Thrust (ob->angle,-controly*MOVESCALE); // move forwards
235 }
236 else if (controly > 0)
237 {
238 angle = ob->angle + ANGLES/2;
239 if (angle >= ANGLES)
240 angle -= ANGLES;
241 Thrust (angle,controly*BACKMOVESCALE); // move backwards
242 }
243
244 if (gamestate.victoryflag) // watching the BJ actor
245 return;
246}
247
248/*
249=============================================================================
250
251 STATUS WINDOW STUFF
252
253=============================================================================
254*/
255
256
257/*
258==================
259=
260= StatusDrawPic
261=
262==================
263*/
264
265void StatusDrawPic (unsigned x, unsigned y, unsigned picnum)
266{
267 LatchDrawPicScaledCoord ((screenWidth-scaleFactor*320)/16 + scaleFactor*x,
268 screenHeight-scaleFactor*(STATUSLINES-y),picnum);
269}
270
271void StatusDrawFace(unsigned picnum)
272{
273 StatusDrawPic(17, 4, picnum);
274
275#ifdef _arch_dreamcast
276 DC_StatusDrawLCD(picnum);
277#endif
278}
279
280
281/*
282==================
283=
284= DrawFace
285=
286==================
287*/
288
289void DrawFace (void)
290{
291 if(viewsize == 21 && ingame) return;
292 if (SD_SoundPlaying() == GETGATLINGSND)
293 StatusDrawFace(GOTGATLINGPIC);
294 else if (gamestate.health)
295 {
296#ifdef SPEAR
297 if (godmode)
298 StatusDrawFace(GODMODEFACE1PIC+gamestate.faceframe);
299 else
300#endif
301 StatusDrawFace(FACE1APIC+3*((100-gamestate.health)/16)+gamestate.faceframe);
302 }
303 else
304 {
305#ifndef SPEAR
306 if (LastAttacker && LastAttacker->obclass == needleobj)
307 StatusDrawFace(MUTANTBJPIC);
308 else
309#endif
310 StatusDrawFace(FACE8APIC);
311 }
312}
313
314/*
315===============
316=
317= UpdateFace
318=
319= Calls draw face if time to change
320=
321===============
322*/
323
324int facecount = 0;
325int facetimes = 0;
326
327void UpdateFace (void)
328{
329 // don't make demo depend on sound playback
330 if(demoplayback || demorecord)
331 {
332 if(facetimes > 0)
333 {
334 facetimes--;
335 return;
336 }
337 }
338 else if(SD_SoundPlaying() == GETGATLINGSND)
339 return;
340
341 facecount += tics;
342 if (facecount > US_RndT())
343 {
344 gamestate.faceframe = (US_RndT()>>6);
345 if (gamestate.faceframe==3)
346 gamestate.faceframe = 1;
347
348 facecount = 0;
349 DrawFace ();
350 }
351}
352
353
354
355/*
356===============
357=
358= LatchNumber
359=
360= right justifies and pads with blanks
361=
362===============
363*/
364
365static void LatchNumber (int x, int y, unsigned width, int32_t number)
366{
367 unsigned length,c;
368 char str[20];
369
370 ltoa (number,str,10);
371
372 length = (unsigned) strlen (str);
373
374 while (length<width)
375 {
376 StatusDrawPic (x,y,N_BLANKPIC);
377 x++;
378 width--;
379 }
380
381 c = length <= width ? 0 : length-width;
382
383 while (c<length)
384 {
385 StatusDrawPic (x,y,str[c]-'0'+ N_0PIC);
386 x++;
387 c++;
388 }
389}
390
391
392/*
393===============
394=
395= DrawHealth
396=
397===============
398*/
399
400void DrawHealth (void)
401{
402 if(viewsize == 21 && ingame) return;
403 LatchNumber (21,16,3,gamestate.health);
404}
405
406
407/*
408===============
409=
410= TakeDamage
411=
412===============
413*/
414
415void TakeDamage (int points,objtype *attacker)
416{
417 LastAttacker = attacker;
418
419 if (gamestate.victoryflag)
420 return;
421 if (gamestate.difficulty==gd_baby)
422 points>>=2;
423
424 if (!godmode)
425 gamestate.health -= points;
426
427 if (gamestate.health<=0)
428 {
429 gamestate.health = 0;
430 playstate = ex_died;
431 killerobj = attacker;
432 }
433
434 if (godmode != 2)
435 StartDamageFlash (points);
436
437 DrawHealth ();
438 DrawFace ();
439
440 //
441 // MAKE BJ'S EYES BUG IF MAJOR DAMAGE!
442 //
443#ifdef SPEAR
444 if (points > 30 && gamestate.health!=0 && !godmode && viewsize != 21)
445 {
446 StatusDrawFace(BJOUCHPIC);
447 facecount = 0;
448 }
449#endif
450}
451
452/*
453===============
454=
455= HealSelf
456=
457===============
458*/
459
460void HealSelf (int points)
461{
462 gamestate.health += points;
463 if (gamestate.health>100)
464 gamestate.health = 100;
465
466 DrawHealth ();
467 DrawFace ();
468}
469
470
471//===========================================================================
472
473
474/*
475===============
476=
477= DrawLevel
478=
479===============
480*/
481
482void DrawLevel (void)
483{
484 if(viewsize == 21 && ingame) return;
485#ifdef SPEAR
486 if (gamestate.mapon == 20)
487 LatchNumber (2,16,2,18);
488 else
489#endif
490 LatchNumber (2,16,2,gamestate.mapon+1);
491}
492
493//===========================================================================
494
495
496/*
497===============
498=
499= DrawLives
500=
501===============
502*/
503
504void DrawLives (void)
505{
506 if(viewsize == 21 && ingame) return;
507 LatchNumber (14,16,1,gamestate.lives);
508}
509
510
511/*
512===============
513=
514= GiveExtraMan
515=
516===============
517*/
518
519void GiveExtraMan (void)
520{
521 if (gamestate.lives<9)
522 gamestate.lives++;
523 DrawLives ();
524 SD_PlaySound (BONUS1UPSND);
525}
526
527//===========================================================================
528
529/*
530===============
531=
532= DrawScore
533=
534===============
535*/
536
537void DrawScore (void)
538{
539 if(viewsize == 21 && ingame) return;
540 LatchNumber (6,16,6,gamestate.score);
541}
542
543/*
544===============
545=
546= GivePoints
547=
548===============
549*/
550
551void GivePoints (int32_t points)
552{
553 gamestate.score += points;
554 while (gamestate.score >= gamestate.nextextra)
555 {
556 gamestate.nextextra += EXTRAPOINTS;
557 GiveExtraMan ();
558 }
559 DrawScore ();
560}
561
562//===========================================================================
563
564/*
565==================
566=
567= DrawWeapon
568=
569==================
570*/
571
572void DrawWeapon (void)
573{
574 if(viewsize == 21 && ingame) return;
575 StatusDrawPic (32,8,KNIFEPIC+gamestate.weapon);
576}
577
578
579/*
580==================
581=
582= DrawKeys
583=
584==================
585*/
586
587void DrawKeys (void)
588{
589 if(viewsize == 21 && ingame) return;
590 if (gamestate.keys & 1)
591 StatusDrawPic (30,4,GOLDKEYPIC);
592 else
593 StatusDrawPic (30,4,NOKEYPIC);
594
595 if (gamestate.keys & 2)
596 StatusDrawPic (30,20,SILVERKEYPIC);
597 else
598 StatusDrawPic (30,20,NOKEYPIC);
599}
600
601/*
602==================
603=
604= GiveWeapon
605=
606==================
607*/
608
609void GiveWeapon (int weapon)
610{
611 GiveAmmo (6);
612
613 if (gamestate.bestweapon<weapon)
614 gamestate.bestweapon = gamestate.weapon
615 = gamestate.chosenweapon = (weapontype) weapon;
616
617 DrawWeapon ();
618}
619
620//===========================================================================
621
622/*
623===============
624=
625= DrawAmmo
626=
627===============
628*/
629
630void DrawAmmo (void)
631{
632 if(viewsize == 21 && ingame) return;
633 LatchNumber (27,16,2,gamestate.ammo);
634}
635
636/*
637===============
638=
639= GiveAmmo
640=
641===============
642*/
643
644void GiveAmmo (int ammo)
645{
646 if (!gamestate.ammo) // knife was out
647 {
648 if (!gamestate.attackframe)
649 {
650 gamestate.weapon = gamestate.chosenweapon;
651 DrawWeapon ();
652 }
653 }
654 gamestate.ammo += ammo;
655 if (gamestate.ammo > 99)
656 gamestate.ammo = 99;
657 DrawAmmo ();
658}
659
660//===========================================================================
661
662/*
663==================
664=
665= GiveKey
666=
667==================
668*/
669
670void GiveKey (int key)
671{
672 gamestate.keys |= (1<<key);
673 DrawKeys ();
674}
675
676
677
678/*
679=============================================================================
680
681 MOVEMENT
682
683=============================================================================
684*/
685
686
687/*
688===================
689=
690= GetBonus
691=
692===================
693*/
694void GetBonus (statobj_t *check)
695{
696 switch (check->itemnumber)
697 {
698 case bo_firstaid:
699 if (gamestate.health == 100)
700 return;
701
702 SD_PlaySound (HEALTH2SND);
703 HealSelf (25);
704 break;
705
706 case bo_key1:
707 case bo_key2:
708 case bo_key3:
709 case bo_key4:
710 GiveKey (check->itemnumber - bo_key1);
711 SD_PlaySound (GETKEYSND);
712 break;
713
714 case bo_cross:
715 SD_PlaySound (BONUS1SND);
716 GivePoints (100);
717 gamestate.treasurecount++;
718 break;
719 case bo_chalice:
720 SD_PlaySound (BONUS2SND);
721 GivePoints (500);
722 gamestate.treasurecount++;
723 break;
724 case bo_bible:
725 SD_PlaySound (BONUS3SND);
726 GivePoints (1000);
727 gamestate.treasurecount++;
728 break;
729 case bo_crown:
730 SD_PlaySound (BONUS4SND);
731 GivePoints (5000);
732 gamestate.treasurecount++;
733 break;
734
735 case bo_clip:
736 if (gamestate.ammo == 99)
737 return;
738
739 SD_PlaySound (GETAMMOSND);
740 GiveAmmo (8);
741 break;
742 case bo_clip2:
743 if (gamestate.ammo == 99)
744 return;
745
746 SD_PlaySound (GETAMMOSND);
747 GiveAmmo (4);
748 break;
749
750#ifdef SPEAR
751 case bo_25clip:
752 if (gamestate.ammo == 99)
753 return;
754
755 SD_PlaySound (GETAMMOBOXSND);
756 GiveAmmo (25);
757 break;
758#endif
759
760 case bo_machinegun:
761 SD_PlaySound (GETMACHINESND);
762 GiveWeapon (wp_machinegun);
763 break;
764 case bo_chaingun:
765 SD_PlaySound (GETGATLINGSND);
766 facetimes = 38;
767 GiveWeapon (wp_chaingun);
768
769 if(viewsize != 21)
770 StatusDrawFace (GOTGATLINGPIC);
771 facecount = 0;
772 break;
773
774 case bo_fullheal:
775 SD_PlaySound (BONUS1UPSND);
776 HealSelf (99);
777 GiveAmmo (25);
778 GiveExtraMan ();
779 gamestate.treasurecount++;
780 break;
781
782 case bo_food:
783 if (gamestate.health == 100)
784 return;
785
786 SD_PlaySound (HEALTH1SND);
787 HealSelf (10);
788 break;
789
790 case bo_alpo:
791 if (gamestate.health == 100)
792 return;
793
794 SD_PlaySound (HEALTH1SND);
795 HealSelf (4);
796 break;
797
798 case bo_gibs:
799 if (gamestate.health >10)
800 return;
801
802 SD_PlaySound (SLURPIESND);
803 HealSelf (1);
804 break;
805
806#ifdef SPEAR
807 case bo_spear:
808 spearflag = true;
809 spearx = player->x;
810 speary = player->y;
811 spearangle = player->angle;
812 playstate = ex_completed;
813#endif
814 }
815
816 StartBonusFlash ();
817 check->shapenum = -1; // remove from list
818}
819
820/*
821===================
822=
823= TryMove
824=
825= returns true if move ok
826= debug: use pointers to optimize
827===================
828*/
829
830boolean TryMove (objtype *ob)
831{
832 int xl,yl,xh,yh,x,y;
833 objtype *check;
834 int32_t deltax,deltay;
835
836 xl = (ob->x-PLAYERSIZE) >>TILESHIFT;
837 yl = (ob->y-PLAYERSIZE) >>TILESHIFT;
838
839 xh = (ob->x+PLAYERSIZE) >>TILESHIFT;
840 yh = (ob->y+PLAYERSIZE) >>TILESHIFT;
841
842#define PUSHWALLMINDIST PLAYERSIZE
843
844 //
845 // check for solid walls
846 //
847 for (y=yl;y<=yh;y++)
848 {
849 for (x=xl;x<=xh;x++)
850 {
851 check = actorat[x][y];
852 if (check && !ISPOINTER(check))
853 {
854 if(tilemap[x][y]==64 && x==pwallx && y==pwally) // back of moving pushwall?
855 {
856 switch(pwalldir)
857 {
858 case di_north:
859 if(ob->y-PUSHWALLMINDIST<=(pwally<<TILESHIFT)+((63-pwallpos)<<10))
860 return false;
861 break;
862 case di_west:
863 if(ob->x-PUSHWALLMINDIST<=(pwallx<<TILESHIFT)+((63-pwallpos)<<10))
864 return false;
865 break;
866 case di_east:
867 if(ob->x+PUSHWALLMINDIST>=(pwallx<<TILESHIFT)+(pwallpos<<10))
868 return false;
869 break;
870 case di_south:
871 if(ob->y+PUSHWALLMINDIST>=(pwally<<TILESHIFT)+(pwallpos<<10))
872 return false;
873 break;
874 }
875 }
876 else return false;
877 }
878 }
879 }
880
881 //
882 // check for actors
883 //
884 if (yl>0)
885 yl--;
886 if (yh<MAPSIZE-1)
887 yh++;
888 if (xl>0)
889 xl--;
890 if (xh<MAPSIZE-1)
891 xh++;
892
893 for (y=yl;y<=yh;y++)
894 {
895 for (x=xl;x<=xh;x++)
896 {
897 check = actorat[x][y];
898 if (ISPOINTER(check) && check != player && (check->flags & FL_SHOOTABLE) )
899 {
900 deltax = ob->x - check->x;
901 if (deltax < -MINACTORDIST || deltax > MINACTORDIST)
902 continue;
903 deltay = ob->y - check->y;
904 if (deltay < -MINACTORDIST || deltay > MINACTORDIST)
905 continue;
906
907 return false;
908 }
909 }
910 }
911
912 return true;
913}
914
915
916/*
917===================
918=
919= ClipMove
920=
921===================
922*/
923
924void ClipMove (objtype *ob, int32_t xmove, int32_t ymove)
925{
926 int32_t basex,basey;
927
928 basex = ob->x;
929 basey = ob->y;
930
931 ob->x = basex+xmove;
932 ob->y = basey+ymove;
933 if (TryMove (ob))
934 return;
935
936#ifndef REMDEBUG
937 if (noclip && ob->x > 2*TILEGLOBAL && ob->y > 2*TILEGLOBAL
938 && ob->x < (((int32_t)(mapwidth-1))<<TILESHIFT)
939 && ob->y < (((int32_t)(mapheight-1))<<TILESHIFT) )
940 return; // walk through walls
941#endif
942
943 if (!SD_SoundPlaying())
944 SD_PlaySound (HITWALLSND);
945
946 ob->x = basex+xmove;
947 ob->y = basey;
948 if (TryMove (ob))
949 return;
950
951 ob->x = basex;
952 ob->y = basey+ymove;
953 if (TryMove (ob))
954 return;
955
956 ob->x = basex;
957 ob->y = basey;
958}
959
960//==========================================================================
961
962/*
963===================
964=
965= VictoryTile
966=
967===================
968*/
969
970void VictoryTile (void)
971{
972#ifndef SPEAR
973 SpawnBJVictory ();
974#endif
975
976 gamestate.victoryflag = true;
977}
978
979/*
980===================
981=
982= Thrust
983=
984===================
985*/
986
987// For player movement in demos exactly as in the original Wolf3D v1.4 source code
988static fixed FixedByFracOrig(fixed a, fixed b)
989{
990 int sign = 0;
991 if(b == 65536) b = 65535;
992 else if(b == -65536) b = 65535, sign = 1;
993 else if(b < 0) b = (-b), sign = 1;
994
995 if(a < 0)
996 {
997 a = -a;
998 sign = !sign;
999 }
1000 fixed res = (fixed)(((int64_t) a * b) >> 16);
1001 if(sign)
1002 res = -res;
1003 return res;
1004}
1005
1006void Thrust (int angle, int32_t speed)
1007{
1008 int32_t xmove,ymove;
1009 unsigned offset;
1010
1011
1012 //
1013 // ZERO FUNNY COUNTER IF MOVED!
1014 //
1015#ifdef SPEAR
1016 if (speed)
1017 funnyticount = 0;
1018#endif
1019
1020 thrustspeed += speed;
1021 //
1022 // moving bounds speed
1023 //
1024 if (speed >= MINDIST*2)
1025 speed = MINDIST*2-1;
1026
1027 xmove = DEMOCHOOSE_ORIG_SDL(
1028 FixedByFracOrig(speed, costable[angle]),
1029 FixedMul(speed,costable[angle]));
1030 ymove = DEMOCHOOSE_ORIG_SDL(
1031 -FixedByFracOrig(speed, sintable[angle]),
1032 -FixedMul(speed,sintable[angle]));
1033
1034 ClipMove(player,xmove,ymove);
1035
1036 player->tilex = (short)(player->x >> TILESHIFT); // scale to tile values
1037 player->tiley = (short)(player->y >> TILESHIFT);
1038
1039 offset = (player->tiley<<mapshift)+player->tilex;
1040 player->areanumber = *(mapsegs[0] + offset) -AREATILE;
1041
1042 if (*(mapsegs[1] + offset) == EXITTILE)
1043 VictoryTile ();
1044}
1045
1046
1047/*
1048=============================================================================
1049
1050 ACTIONS
1051
1052=============================================================================
1053*/
1054
1055
1056/*
1057===============
1058=
1059= Cmd_Fire
1060=
1061===============
1062*/
1063
1064void Cmd_Fire (void)
1065{
1066 buttonheld[bt_attack] = true;
1067
1068 gamestate.weaponframe = 0;
1069
1070 player->state = &s_attack;
1071
1072 gamestate.attackframe = 0;
1073 gamestate.attackcount =
1074 attackinfo[gamestate.weapon][gamestate.attackframe].tics;
1075 gamestate.weaponframe =
1076 attackinfo[gamestate.weapon][gamestate.attackframe].frame;
1077}
1078
1079//===========================================================================
1080
1081/*
1082===============
1083=
1084= Cmd_Use
1085=
1086===============
1087*/
1088
1089void Cmd_Use (void)
1090{
1091 int checkx,checky,doornum,dir;
1092 boolean elevatorok;
1093
1094 //
1095 // find which cardinal direction the player is facing
1096 //
1097 if (player->angle < ANGLES/8 || player->angle > 7*ANGLES/8)
1098 {
1099 checkx = player->tilex + 1;
1100 checky = player->tiley;
1101 dir = di_east;
1102 elevatorok = true;
1103 }
1104 else if (player->angle < 3*ANGLES/8)
1105 {
1106 checkx = player->tilex;
1107 checky = player->tiley-1;
1108 dir = di_north;
1109 elevatorok = false;
1110 }
1111 else if (player->angle < 5*ANGLES/8)
1112 {
1113 checkx = player->tilex - 1;
1114 checky = player->tiley;
1115 dir = di_west;
1116 elevatorok = true;
1117 }
1118 else
1119 {
1120 checkx = player->tilex;
1121 checky = player->tiley + 1;
1122 dir = di_south;
1123 elevatorok = false;
1124 }
1125
1126 doornum = tilemap[checkx][checky];
1127 if (*(mapsegs[1]+(checky<<mapshift)+checkx) == PUSHABLETILE)
1128 {
1129 //
1130 // pushable wall
1131 //
1132
1133 buttonheld[bt_use] = true;
1134 buttonstate[bt_attack] = false;
1135
1136 PushWall (checkx,checky,dir);
1137 return;
1138 }
1139 if (!buttonheld[bt_use] && doornum == ELEVATORTILE && elevatorok)
1140 {
1141 //
1142 // use elevator
1143 //
1144 buttonheld[bt_use] = true;
1145 buttonstate[bt_attack] = false;
1146
1147 tilemap[checkx][checky]++; // flip switch
1148 if (*(mapsegs[0]+(player->tiley<<mapshift)+player->tilex) == ALTELEVATORTILE)
1149 playstate = ex_secretlevel;
1150 else
1151 playstate = ex_completed;
1152 SD_PlaySound (LEVELDONESND);
1153 SD_WaitSoundDone();
1154 }
1155 else if (!buttonheld[bt_use] && doornum & 0x80)
1156 {
1157 buttonheld[bt_use] = true;
1158 buttonstate[bt_attack] = false;
1159 OperateDoor (doornum & ~0x80);
1160 }
1161 else
1162 SD_PlaySound (DONOTHINGSND);
1163}
1164
1165/*
1166=============================================================================
1167
1168 PLAYER CONTROL
1169
1170=============================================================================
1171*/
1172
1173
1174
1175/*
1176===============
1177=
1178= SpawnPlayer
1179=
1180===============
1181*/
1182
1183void SpawnPlayer (int tilex, int tiley, int dir)
1184{
1185 player->obclass = playerobj;
1186 player->active = ac_yes;
1187 player->tilex = tilex;
1188 player->tiley = tiley;
1189 player->areanumber = (byte) *(mapsegs[0]+(player->tiley<<mapshift)+player->tilex);
1190 player->x = ((int32_t)tilex<<TILESHIFT)+TILEGLOBAL/2;
1191 player->y = ((int32_t)tiley<<TILESHIFT)+TILEGLOBAL/2;
1192 player->state = &s_player;
1193 player->angle = (1-dir)*90;
1194 if (player->angle<0)
1195 player->angle += ANGLES;
1196 player->flags = FL_NEVERMARK;
1197 Thrust (0,0); // set some variables
1198
1199 InitAreas ();
1200}
1201
1202
1203//===========================================================================
1204
1205/*
1206===============
1207=
1208= T_KnifeAttack
1209=
1210= Update player hands, and try to do damage when the proper frame is reached
1211=
1212===============
1213*/
1214
1215void KnifeAttack (objtype *ob)
1216{
1217 objtype *check,*closest;
1218 int32_t dist;
1219
1220 SD_PlaySound (ATKKNIFESND);
1221 // actually fire
1222 dist = 0x7fffffff;
1223 closest = NULL;
1224 for (check=ob->next; check; check=check->next)
1225 {
1226 if ( (check->flags & FL_SHOOTABLE) && (check->flags & FL_VISABLE)
1227 && abs(check->viewx-centerx) < shootdelta)
1228 {
1229 if (check->transx < dist)
1230 {
1231 dist = check->transx;
1232 closest = check;
1233 }
1234 }
1235 }
1236
1237 if (!closest || dist > 0x18000l)
1238 {
1239 // missed
1240 return;
1241 }
1242
1243 // hit something
1244 DamageActor (closest,US_RndT() >> 4);
1245}
1246
1247
1248
1249void GunAttack (objtype *ob)
1250{
1251 objtype *check,*closest,*oldclosest;
1252 int damage;
1253 int dx,dy,dist;
1254 int32_t viewdist;
1255
1256 switch (gamestate.weapon)
1257 {
1258 case wp_pistol:
1259 SD_PlaySound (ATKPISTOLSND);
1260 break;
1261 case wp_machinegun:
1262 SD_PlaySound (ATKMACHINEGUNSND);
1263 break;
1264 case wp_chaingun:
1265 SD_PlaySound (ATKGATLINGSND);
1266 break;
1267 }
1268
1269 madenoise = true;
1270
1271 //
1272 // find potential targets
1273 //
1274 viewdist = 0x7fffffffl;
1275 closest = NULL;
1276
1277 while (1)
1278 {
1279 oldclosest = closest;
1280
1281 for (check=ob->next ; check ; check=check->next)
1282 {
1283 if ((check->flags & FL_SHOOTABLE) && (check->flags & FL_VISABLE)
1284 && abs(check->viewx-centerx) < shootdelta)
1285 {
1286 if (check->transx < viewdist)
1287 {
1288 viewdist = check->transx;
1289 closest = check;
1290 }
1291 }
1292 }
1293
1294 if (closest == oldclosest)
1295 return; // no more targets, all missed
1296
1297 //
1298 // trace a line from player to enemey
1299 //
1300 if (CheckLine(closest))
1301 break;
1302 }
1303
1304 //
1305 // hit something
1306 //
1307 dx = ABS(closest->tilex - player->tilex);
1308 dy = ABS(closest->tiley - player->tiley);
1309 dist = dx>dy ? dx:dy;
1310 if (dist<2)
1311 damage = US_RndT() / 4;
1312 else if (dist<4)
1313 damage = US_RndT() / 6;
1314 else
1315 {
1316 if ( (US_RndT() / 12) < dist) // missed
1317 return;
1318 damage = US_RndT() / 6;
1319 }
1320 DamageActor (closest,damage);
1321}
1322
1323//===========================================================================
1324
1325/*
1326===============
1327=
1328= VictorySpin
1329=
1330===============
1331*/
1332
1333void VictorySpin (void)
1334{
1335 int32_t desty;
1336
1337 if (player->angle > 270)
1338 {
1339 player->angle -= (short)(tics * 3);
1340 if (player->angle < 270)
1341 player->angle = 270;
1342 }
1343 else if (player->angle < 270)
1344 {
1345 player->angle += (short)(tics * 3);
1346 if (player->angle > 270)
1347 player->angle = 270;
1348 }
1349
1350 desty = (((int32_t)player->tiley-5)<<TILESHIFT)-0x3000;
1351
1352 if (player->y > desty)
1353 {
1354 player->y -= tics*4096;
1355 if (player->y < desty)
1356 player->y = desty;
1357 }
1358}
1359
1360
1361//===========================================================================
1362
1363/*
1364===============
1365=
1366= T_Attack
1367=
1368===============
1369*/
1370
1371void T_Attack (objtype *ob)
1372{
1373 struct atkinf *cur;
1374
1375 UpdateFace ();
1376
1377 if (gamestate.victoryflag) // watching the BJ actor
1378 {
1379 VictorySpin ();
1380 return;
1381 }
1382
1383 if ( buttonstate[bt_use] && !buttonheld[bt_use] )
1384 buttonstate[bt_use] = false;
1385
1386 if ( buttonstate[bt_attack] && !buttonheld[bt_attack])
1387 buttonstate[bt_attack] = false;
1388
1389 ControlMovement (ob);
1390 if (gamestate.victoryflag) // watching the BJ actor
1391 return;
1392
1393 plux = (word) (player->x >> UNSIGNEDSHIFT); // scale to fit in unsigned
1394 pluy = (word) (player->y >> UNSIGNEDSHIFT);
1395 player->tilex = (short)(player->x >> TILESHIFT); // scale to tile values
1396 player->tiley = (short)(player->y >> TILESHIFT);
1397
1398 //
1399 // change frame and fire
1400 //
1401 gamestate.attackcount -= (short) tics;
1402 while (gamestate.attackcount <= 0)
1403 {
1404 cur = &attackinfo[gamestate.weapon][gamestate.attackframe];
1405 switch (cur->attack)
1406 {
1407 case -1:
1408 ob->state = &s_player;
1409 if (!gamestate.ammo)
1410 {
1411 gamestate.weapon = wp_knife;
1412 DrawWeapon ();
1413 }
1414 else
1415 {
1416 if (gamestate.weapon != gamestate.chosenweapon)
1417 {
1418 gamestate.weapon = gamestate.chosenweapon;
1419 DrawWeapon ();
1420 }
1421 }
1422 gamestate.attackframe = gamestate.weaponframe = 0;
1423 return;
1424
1425 case 4:
1426 if (!gamestate.ammo)
1427 break;
1428 if (buttonstate[bt_attack])
1429 gamestate.attackframe -= 2;
1430 case 1:
1431 if (!gamestate.ammo)
1432 { // can only happen with chain gun
1433 gamestate.attackframe++;
1434 break;
1435 }
1436 GunAttack (ob);
1437 if (!ammocheat)
1438 gamestate.ammo--;
1439 DrawAmmo ();
1440 break;
1441
1442 case 2:
1443 KnifeAttack (ob);
1444 break;
1445
1446 case 3:
1447 if (gamestate.ammo && buttonstate[bt_attack])
1448 gamestate.attackframe -= 2;
1449 break;
1450 }
1451
1452 gamestate.attackcount += cur->tics;
1453 gamestate.attackframe++;
1454 gamestate.weaponframe =
1455 attackinfo[gamestate.weapon][gamestate.attackframe].frame;
1456 }
1457}
1458
1459
1460
1461//===========================================================================
1462
1463/*
1464===============
1465=
1466= T_Player
1467=
1468===============
1469*/
1470
1471static int last_use = 0;
1472
1473void T_Player (objtype *ob)
1474{
1475 if (gamestate.victoryflag) // watching the BJ actor
1476 {
1477 VictorySpin ();
1478 return;
1479 }
1480
1481 UpdateFace ();
1482 CheckWeaponChange ();
1483
1484 // weird
1485 if( buttonstate[bt_attack] )
1486 Cmd_Use ();
1487
1488 if ( buttonstate[bt_attack] && !buttonheld[bt_attack])
1489 Cmd_Fire ();
1490
1491 ControlMovement (ob);
1492 if (gamestate.victoryflag) // watching the BJ actor
1493 return;
1494
1495 plux = (word) (player->x >> UNSIGNEDSHIFT); // scale to fit in unsigned
1496 pluy = (word) (player->y >> UNSIGNEDSHIFT);
1497 player->tilex = (short)(player->x >> TILESHIFT); // scale to tile values
1498 player->tiley = (short)(player->y >> TILESHIFT);
1499}