summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/wolf3d/wl_agent.c
diff options
context:
space:
mode:
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}