home *** CD-ROM | disk | FTP | other *** search
/ C++ Games Programming / CPPGAMES.ISO / thx / demos / shootout / build / sheriff.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-06  |  6.1 KB  |  312 lines

  1. // ------------ sheriff.cpp
  2.  
  3. #include "shootout.h"
  4. #include "options.h"
  5.  
  6. CUELIST(Sheriff)
  7.     KEYSTROKE(UP,   OnShoot)
  8.     KEYSTROKE(DN,   OnShoot)
  9.     KEYSTROKE(PGUP, OnShoot)
  10.     KEYSTROKE(HOME, OnShoot)
  11.     KEYSTROKE(RT,   OnChangeDirection)
  12.     KEYSTROKE(LF,   OnChangeDirection)
  13.     KEYSTROKE('r',  OnReload)
  14.     KEYSTROKE('x',  OnResurrection)
  15. ENDCUELIST
  16.  
  17. const short int FirstX = 15;
  18. const short int FirstY = 120;
  19. // --- step increments of the sheriff's stroll
  20. short int Sheriff::walkincr[] = { 5,7,6,7 };
  21. // ---- frame imageno array for the 4 shoot sequences
  22. short int Sheriff::shoot[4][5] = {
  23.     {11,12,13,12,27},
  24.     {14,15,16,15,14},
  25.     {17,18,19,18,17},
  26.     {20,21,22,21,20}
  27. };
  28.  
  29. const int walkinterval = 2;
  30. const int shootinterval = 2;
  31.  
  32. Sheriff::Sheriff() : Player("sheriff.gfx", "sounds.sfx", walkinterval)
  33. {
  34. }
  35.  
  36. void Sheriff::initialize_sheriff()
  37. {
  38.     frame = 0;
  39.     incr = 1;
  40.     setx(FirstX);
  41.     sety(FirstY);
  42.     of = 0;
  43.     offset = 0;
  44.     steps = 0;
  45.     forward = 1;
  46.     mode = walk;
  47.     shootseq = 0;
  48.     bullets = 6;
  49.     ((Shootout*)director)->bullets->setnum(bullets);
  50.     deadx = 0;
  51.     resurrections = 0;
  52.     setinterval(walkinterval);
  53.     disappear();
  54. }
  55. void Sheriff::OnResurrection(int)
  56. {
  57.     if (mode == dead)
  58.         mode = resurrecting;
  59. }
  60. // ----- keyboard shoot command callback function
  61. void Sheriff::OnShoot(int key)
  62. {
  63.     if (!isdead() && mode != falling)    {
  64.         setinterval(shootinterval);
  65.         switch (key)    {
  66.             case UP:
  67.                 mode = rear;
  68.                 break;
  69.             case DN:
  70.                 mode = front;
  71.                 break;
  72.             case PGUP:
  73.                 mode = right;
  74.                 break;
  75.             case HOME:
  76.                 mode = left;
  77.                 break;
  78.             default:
  79.                 break;
  80.         }
  81.     }
  82. }
  83. // ---- the frame animation entry point from Theatrix
  84. void Sheriff::update_position()
  85. {
  86.     int y;
  87.     switch (mode)    {
  88.         case walk:
  89.             Walk();
  90.             break;
  91.         case dying:
  92.             // ----- sheriff got shot
  93.             set_imageno(forward ? 23 : 24);
  94.             deadx = getx();
  95.             if (deadx > 240)
  96.                 setx(240);
  97.             mode = falling;
  98.         case falling:
  99.             setinterval(1);
  100.             y = gety();
  101.             if (y < sidewalk+20)
  102.                 sety(y+10);
  103.             else
  104.                 mode = dead;
  105.             break;
  106.         case dead:
  107.             // ---- sheriff got killed
  108.             break;
  109.         case resurrecting:
  110.             if (((Shootout*)director)->parsonisdead())    {
  111.                 // --- can't be resurrected if you kill the parson
  112.                 ((Shootout*)director)->deathcertificate(1);
  113.                 mode = dead;
  114.             }
  115.             else if (resurrections < options->resurrections->getnum())    {
  116.                 mode = resurrected;
  117.                 resurrections++;
  118.             }
  119.             else    {
  120.                 ((Shootout*)director)->deathcertificate(2);
  121.                 mode = dead;
  122.             }
  123.             break;
  124.         case resurrected:
  125.             bullets = 6;
  126.             ((Shootout*)director)->bullets->setnum(bullets);
  127.             set_imageno(frame+offset);
  128.             sety(FirstY);
  129.             setx(deadx);
  130.             mode = walk;
  131.             break;
  132.         case reload:
  133.             Reload();
  134.             break;
  135.         default:
  136.             Shoot(mode);
  137.             break;
  138.     }
  139. }
  140. // ---- reloading
  141. void Sheriff::Reload()
  142. {
  143.     short int im = get_imageno();
  144.     switch (im)    {
  145.         case 11:
  146.             set_imageno(25);
  147.             break;
  148.         case 25:
  149.             set_imageno(26);
  150.             break;
  151.         case 26:
  152.             if (bullets == 6)    {
  153.                 mode = walk;
  154.                 set_imageno(11);
  155.                 break;
  156.             }
  157.             set_imageno(25);
  158.             bullets++;
  159.             ((Shootout*)director)->bullets->setnum(bullets);
  160.             break;
  161.         default:
  162.             break;
  163.     }
  164. }
  165. // ---- point sheriff in the opposite direction
  166. void Sheriff::OnChangeDirection(int ky)
  167. {
  168.     if (forward && ky == RT)
  169.         return;
  170.     if (!forward && ky == LF)
  171.         return;
  172.     forward ^= 1;
  173.     steps = 39-steps;
  174.     offset = 5-offset;
  175. }
  176. // ---- play a frame of the sheriff's walk animation sequence
  177. void Sheriff::Walk()
  178. {
  179.     setinterval(walkinterval);
  180.     if (++steps == 40)    {
  181.         steps = 0;
  182.         forward ^= 1;
  183.         incr = 1;
  184.         of = 0;
  185.         frame = 0;
  186.         if (forward)    {
  187.             offset = 0;
  188.             setx(FirstX);
  189.         }
  190.         else 
  191.             offset = 5;
  192.     }
  193.     else    {
  194.         if (forward)
  195.             setx(getx() + walkincr[of]);
  196.         else 
  197.             setx(getx() - walkincr[of]);
  198.         if (++of == 4)
  199.             of = 0;
  200.     }
  201.     frame += incr;
  202.     if (frame == 5)
  203.         incr = -1;
  204.     else if (frame == 1)
  205.         incr = 1;
  206.     set_imageno(frame+offset);
  207. }
  208. // --- compute target zone from position and direction of shot
  209. void Sheriff::targetzone(short int& zone1, short int& zone2)
  210. {
  211.     short int tzone = zone();
  212.     zone1 = zone2 = 0;
  213.     if (mode == right)    {
  214.         if (tzone != 5)    {
  215.             zone1 = tzone+1;
  216.             if (zone1 != 5)
  217.                 zone2 = zone1+1;
  218.         }
  219.         return;
  220.     }
  221.     if (mode == left)    {
  222.         if (tzone != 1)    {
  223.             zone1 = tzone-1;
  224.             if (zone1 != 1)
  225.                 zone2 = zone1-1;
  226.         }
  227.         return;
  228.     }
  229.     if (mode == rear)
  230.         zone1 = tzone;
  231. }
  232. // ---- find a target for the latest shot
  233. BitPart *Sheriff::findtarget()
  234. {
  235.     BitPart *acs[maxactors];
  236.     BitPart *bp = 0;
  237.     short int zone1, zone2;
  238.     targetzone(zone1, zone2);
  239.     if (zone1)    {
  240.         int ct = ((Shootout*)director)->findactors(acs, zone1, zone2);
  241.         for (int i = 0; i < ct; i++)    {
  242.             if (bp == 0 || !acs[i]->iscitizen())
  243.                 bp = acs[i];
  244.             if (!acs[i]->iscitizen())
  245.                 break;
  246.         }
  247.     }
  248.     return bp;
  249. }
  250. // ---- fire a shot
  251. inline void Sheriff::fire()
  252. {
  253.     if (bullets > 0)    {
  254.         play_sound_clip(1);
  255.         --bullets;
  256.         ((Shootout*)director)->bullets->setnum(bullets);
  257.         if (mode == front)
  258.             ((Shootout*)director)->shatterscreen();
  259.         else    {
  260.             BitPart *trg = findtarget();
  261.             if (trg != 0)    {
  262.                 if (trg->iscitizen())
  263.                     (*((Shootout*)director)->citizens)++;
  264.                 else
  265.                     (*((Shootout*)director)->badguys)++;
  266.                 trg->getshot();
  267.             }
  268.         }
  269.     }
  270.     else
  271.         play_sound_clip(2);
  272. }
  273. // ---- play a frame of the sheriff's shoot animation sequence
  274. void Sheriff::Shoot(Mode md)
  275. {
  276.     short int shame = (mode == front && bullets > 0);
  277.     if (bullets > 0 || shootseq != 2)
  278.         set_imageno(shoot[md][shootseq]);
  279.     if (shootseq == 2)    // the firing frame
  280.         fire();
  281.     if (shootseq == 3 && mode == front)
  282.         setinterval(10);
  283.     if (++shootseq == 5)    {
  284.         // --- last frame in the sequence
  285.         mode = shame ? dead : walk;
  286.         shootseq = 0;
  287.     }
  288. }
  289. // ---- compute zone (1/5 of the walk) 1 to 5 that the sheriff is in
  290. short int Sheriff::zone()
  291. {
  292.     short int zn = steps/8+1;
  293.     if (!forward)
  294.         zn = (5 - zn) + 1;
  295.     return zn;
  296. }
  297.  
  298. // ------ called to kill the sheriff
  299. void Sheriff::getshot()
  300. {
  301.     mode = dying;
  302. }
  303.  
  304. // ----- reload the gun
  305. void Sheriff::OnReload(int)
  306. {
  307.     if (!isdead() && mode != reload)    {
  308.         mode = reload;
  309.         set_imageno(11);
  310.     }
  311. }
  312.