Subversion Repositories Games.Rick Dangerous

Rev

Rev 1 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * src/e_rick.c
  3.  *
  4.  * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved.
  5.  *
  6.  * The use and distribution terms for this software are contained in the file
  7.  * named README, which can be found in the root of this distribution. By
  8.  * using this software in any fashion, you are agreeing to be bound by the
  9.  * terms of this license.
  10.  *
  11.  * You must not remove this notice, or any other, from this software.
  12.  */
  13.  
  14. #include "system.h"
  15. #include "game.h"
  16. #include "ents.h"
  17. #include "e_rick.h"
  18.  
  19. #include "e_bullet.h"
  20. #include "e_bomb.h"
  21. #include "control.h"
  22. #include "maps.h"
  23. #include "util.h"
  24.  
  25. /*
  26.  * public vars
  27.  */
  28. S16 e_rick_stop_x = 0;
  29. S16 e_rick_stop_y = 0;
  30. U8 e_rick_state = 0;
  31.  
  32. extern U8 want_infiniteammo;
  33.  
  34. /*
  35.  * local vars
  36.  */
  37. static U8 scrawl;
  38.  
  39. static U8 trigger = FALSE;
  40.  
  41. static S8 offsx;
  42. static U8 ylow;
  43. static S16 offsy;
  44.  
  45. static U8 seq;
  46.  
  47. static U8 save_crawl;
  48. static U16 save_x, save_y;
  49.  
  50.  
  51. /*
  52.  * Box test
  53.  *
  54.  * ASM 113E (based on)
  55.  *
  56.  * e: entity to test against (corresponds to SI in asm code -- here DI
  57.  *      is assumed to point to rick).
  58.  * ret: TRUE/intersect, FALSE/not.
  59.  */
  60. U8 e_rick_boxtest (U8 e)
  61. {
  62.    /*
  63.     * rick: x+0x05 to x+0x11, y+[0x08 if rick's crawling] to y+0x14
  64.     * entity: x to x+w, y to y+h
  65.     */
  66.  
  67.    if (E_RICK_ENT.x + 0x11 < ent_ents[e].x
  68.        || E_RICK_ENT.x + 0x05 > ent_ents[e].x + ent_ents[e].w
  69.        || E_RICK_ENT.y + 0x14 < ent_ents[e].y
  70.        || E_RICK_ENT.y + (E_RICK_STTST (E_RICK_STCRAWL) ? 0x08 : 0x00) > ent_ents[e].y + ent_ents[e].h - 1)
  71.       return FALSE;
  72.    else
  73.       return TRUE;
  74. }
  75.  
  76.  
  77. /*
  78.  * Go zombie
  79.  *
  80.  * ASM 1851
  81.  */
  82. void e_rick_gozombie (void)
  83. {
  84.    //return; // cheat
  85.  
  86.    /* already zombie? */
  87.    if (E_RICK_STTST (E_RICK_STZOMBIE))
  88.       return;
  89.  
  90.    syssnd_play (WAV_DIE, 1);
  91.  
  92.    E_RICK_STSET (E_RICK_STZOMBIE);
  93.    offsy = -0x0400;
  94.    offsx = (E_RICK_ENT.x > 0x80 ? -3 : +3);
  95.    ylow = 0;
  96.    E_RICK_ENT.front = TRUE;
  97. }
  98.  
  99.  
  100. /*
  101.  * Action sub-function for e_rick when zombie
  102.  *
  103.  * ASM 17DC
  104.  */
  105. static void e_rick_z_action (void)
  106. {
  107.    U32 i;
  108.  
  109.    /* sprite */
  110.    E_RICK_ENT.sprite = (E_RICK_ENT.x & 0x04) ? 0x1A : 0x19;
  111.  
  112.    /* x */
  113.    E_RICK_ENT.x += offsx;
  114.  
  115.    /* y */
  116.    i = (E_RICK_ENT.y << 8) + offsy + ylow;
  117.    E_RICK_ENT.y = (S16) (i >> 8);
  118.    offsy += 0x80;
  119.    ylow = (U8) i;
  120.  
  121.    /* dead when out of screen */
  122.    if (E_RICK_ENT.y < 0 || E_RICK_ENT.y > 0x0140)
  123.       E_RICK_STSET (E_RICK_STDEAD);
  124. }
  125.  
  126.  
  127. /*
  128.  * Action sub-function for e_rick.
  129.  *
  130.  * ASM 13BE
  131.  */
  132. void e_rick_action2 (void)
  133. {
  134.    U8 env0, env1;
  135.    S16 x, y;
  136.    U32 i;
  137.  
  138.    E_RICK_STRST (E_RICK_STSTOP | E_RICK_STSHOOT);
  139.  
  140.    /* if zombie, run dedicated function and return */
  141.    if E_RICK_STTST(E_RICK_STZOMBIE)
  142.    {
  143.       e_rick_z_action ();
  144.       return;
  145.    }
  146.  
  147.    /* climbing? */
  148.    if (E_RICK_STTST (E_RICK_STCLIMB))
  149.       goto climbing;
  150.  
  151.    /*
  152.     * NOT CLIMBING
  153.     */
  154.    E_RICK_STRST (E_RICK_STJUMP);
  155.  
  156.    /* calc y */
  157.    i = (E_RICK_ENT.y << 8) + offsy + ylow;
  158.    y = (S16) (i >> 8);
  159.  
  160.    /* test environment */
  161.    u_envtest (E_RICK_ENT.x, y, (U8) E_RICK_STTST (E_RICK_STCRAWL), &env0, &env1);
  162.  
  163.    /* stand up, if possible */
  164.    if (E_RICK_STTST (E_RICK_STCRAWL) && !env0)
  165.       E_RICK_STRST (E_RICK_STCRAWL);
  166.  
  167.    /* can move vertically? */
  168.    if (env1 & (offsy < 0 ?
  169.                MAP_EFLG_VERT | MAP_EFLG_SOLID | MAP_EFLG_SPAD
  170.                : MAP_EFLG_VERT | MAP_EFLG_SOLID | MAP_EFLG_SPAD | MAP_EFLG_WAYUP))
  171.       goto vert_not;
  172.  
  173.    /*
  174.     * VERTICAL MOVE
  175.     */
  176.    E_RICK_STSET (E_RICK_STJUMP);
  177.  
  178.    /* killed? */
  179.    if (env1 & MAP_EFLG_LETHAL)
  180.    {
  181.       e_rick_gozombie ();
  182.       return;
  183.    }
  184.  
  185.    /* save */
  186.    E_RICK_ENT.y = y;
  187.    ylow = (U8) i;
  188.  
  189.    /* climb? */
  190.    if ((env1 & MAP_EFLG_CLIMB) && (control_status & (CONTROL_UP | CONTROL_DOWN)))
  191.    {
  192.       offsy = 0x0100;
  193.       E_RICK_STSET (E_RICK_STCLIMB);
  194.       return;
  195.    }
  196.  
  197.    /* fall */
  198.    offsy += 0x0080;
  199.  
  200.    if (offsy > 0x0800)
  201.    {
  202.       offsy = 0x0800;
  203.       ylow = 0;
  204.    }
  205.  
  206.    /*
  207.     * HORIZONTAL MOVE
  208.     */
  209.    horiz:
  210.  
  211.    /* should move? */
  212.    if (!(control_status & (CONTROL_LEFT|CONTROL_RIGHT)))
  213.    {
  214.       seq = 2; /* no: reset seq and return */
  215.       return;
  216.    }
  217.  
  218.    if (control_status & CONTROL_LEFT)
  219.    {
  220.       /* move left */
  221.       x = E_RICK_ENT.x - 2;
  222.       game_dir = LEFT;
  223.  
  224.       if (x < 0)
  225.       {
  226.          /* prev submap */
  227.          game_chsm = TRUE;
  228.          E_RICK_ENT.x = 0xe2;
  229.          return;
  230.       }
  231.    }
  232.    else
  233.    {
  234.       /* move right */
  235.       x = E_RICK_ENT.x + 2;
  236.       game_dir = RIGHT;
  237.  
  238.       if (x >= 0xe8)
  239.       {
  240.          /* next submap */
  241.          game_chsm = TRUE;
  242.          E_RICK_ENT.x = 0x04;
  243.          return;
  244.       }
  245.    }
  246.  
  247.    /* still within this map: test environment */
  248.    u_envtest (x, E_RICK_ENT.y, (U8) E_RICK_STTST (E_RICK_STCRAWL), &env0, &env1);
  249.  
  250.    /* save x-position if it is possible to move */
  251.    if (!(env1 & (MAP_EFLG_SOLID | MAP_EFLG_SPAD | MAP_EFLG_WAYUP)))
  252.    {
  253.       E_RICK_ENT.x = x;
  254.  
  255.       if (env1 & MAP_EFLG_LETHAL)
  256.          e_rick_gozombie ();
  257.    }
  258.  
  259.    /* end */
  260.    return;
  261.  
  262.    /*
  263.     * NO VERTICAL MOVE
  264.     */
  265. vert_not:
  266.    if (offsy < 0)
  267.    {
  268.       /* not climbing + trying to go _up_ not possible -> hit the roof */
  269.       E_RICK_STSET (E_RICK_STJUMP);   /* fall back to the ground */
  270.       E_RICK_ENT.y &= 0xF8;
  271.       offsy = 0;
  272.       ylow = 0;
  273.       goto horiz;
  274.    }
  275.  
  276.    /* else: not climbing + trying to go _down_ not possible -> standing */
  277.    /* align to ground */
  278.    E_RICK_ENT.y &= 0xF8;
  279.    E_RICK_ENT.y |= 0x03;
  280.    ylow = 0;
  281.  
  282.    /* standing on a super pad? */
  283.    if ((env1 & MAP_EFLG_SPAD) && offsy >= 0X0200)
  284.    {
  285.       offsy = (control_status & CONTROL_UP) ? 0xf800 : 0x00fe - offsy;
  286.       syssnd_play (WAV_PAD, 1);
  287.       goto horiz;
  288.    }
  289.  
  290.    offsy = 0x0100;   /* reset*/
  291.  
  292.    /* standing. firing ? */
  293.    if (scrawl || !(control_status & CONTROL_FIRE))
  294.       goto firing_not;
  295.  
  296.    /*
  297.     * FIRING
  298.     */
  299.    if (control_status & (CONTROL_LEFT | CONTROL_RIGHT))
  300.    {
  301.       /* stop */
  302.       if (control_status & CONTROL_RIGHT)
  303.       {
  304.          game_dir = RIGHT;
  305.          e_rick_stop_x = E_RICK_ENT.x + 0x17;
  306.       }
  307.       else
  308.       {
  309.          game_dir = LEFT;
  310.          e_rick_stop_x = E_RICK_ENT.x;
  311.       }
  312.  
  313.       e_rick_stop_y = E_RICK_ENT.y + 0x000E;
  314.       E_RICK_STSET (E_RICK_STSTOP);
  315.       return;
  316.    }
  317.  
  318.    if (control_status == (CONTROL_FIRE | CONTROL_UP))
  319.    {
  320.       /* bullet */
  321.       E_RICK_STSET (E_RICK_STSHOOT);
  322.  
  323.       /* not an automatic gun: shoot once only */
  324.       if (trigger)
  325.          return;
  326.       else
  327.          trigger = TRUE;
  328.  
  329.       /* already a bullet in the air ... that's enough */
  330.       if (E_BULLET_ENT.n)
  331.          return;
  332.  
  333.       /* else use a bullet, if any available */
  334.       if (!want_infiniteammo && !game_bullets)
  335.          return;
  336.  
  337.       /* initialize bullet */
  338.       e_bullet_init (E_RICK_ENT.x, E_RICK_ENT.y);
  339.       if (!want_infiniteammo)
  340.          game_bullets--;
  341.       return;
  342.    }
  343.  
  344.    trigger = FALSE; /* not shooting means trigger is released */
  345.    seq = 0; /* reset */
  346.  
  347.    if (control_status == (CONTROL_FIRE | CONTROL_DOWN))
  348.    {
  349.       /* bomb */
  350.       /* already a bomb ticking ... that's enough */
  351.       if (E_BOMB_ENT.n)
  352.          return;
  353.  
  354.       /* else use a bomb, if any available */
  355.       if (!want_infiniteammo && !game_bombs)
  356.          return;
  357.  
  358.       /* initialize bomb */
  359.       e_bomb_init (E_RICK_ENT.x, E_RICK_ENT.y);
  360.       if (!want_infiniteammo)
  361.          game_bombs--;
  362.       return;
  363.    }
  364.  
  365.    return;
  366.  
  367.    /*
  368.     * NOT FIRING
  369.     */
  370. firing_not:
  371.    if (control_status & CONTROL_UP)
  372.    {
  373.       /* jump or climb */
  374.       if (env1 & MAP_EFLG_CLIMB)
  375.       {
  376.          /* climb */
  377.          E_RICK_STSET (E_RICK_STCLIMB);
  378.          return;
  379.       }
  380.  
  381.       offsy = -0x0580;   /* jump */
  382.       ylow = 0;
  383.       syssnd_play (WAV_JUMP, 1);
  384.       goto horiz;
  385.    }
  386.  
  387.    if (control_status & CONTROL_DOWN)
  388.    {
  389.       /* crawl or climb */
  390.       if ((env1 & MAP_EFLG_VERT)   /* can go down */
  391.           && !(control_status & (CONTROL_LEFT | CONTROL_RIGHT))   /* + not moving horizontaly */
  392.           && (E_RICK_ENT.x & 0x1f) < 0x0a)
  393.       {
  394.          /* + aligned -> climb */
  395.          E_RICK_ENT.x &= 0xf0;
  396.          E_RICK_ENT.x |= 0x04;
  397.          E_RICK_STSET (E_RICK_STCLIMB);
  398.       }
  399.       else
  400.       {
  401.          /* crawl */
  402.          E_RICK_STSET (E_RICK_STCRAWL);
  403.          goto horiz;
  404.       }
  405.  
  406.    }
  407.    goto horiz;
  408.  
  409.    /*
  410.     * CLIMBING
  411.     */
  412. climbing:
  413.    /* should move? */
  414.    if (!(control_status & (CONTROL_UP | CONTROL_DOWN | CONTROL_LEFT | CONTROL_RIGHT)))
  415.    {
  416.       seq = 0; /* no: reset seq and return */
  417.       return;
  418.    }
  419.  
  420.    if (control_status & (CONTROL_UP | CONTROL_DOWN))
  421.    {
  422.       /* up-down: calc new y and test environment */
  423.       y = E_RICK_ENT.y + ((control_status & CONTROL_UP) ? -0x02 : 0x02);
  424.       u_envtest (E_RICK_ENT.x, y, (U8) E_RICK_STTST (E_RICK_STCRAWL), &env0, &env1);
  425.  
  426.       if (env1 & (MAP_EFLG_SOLID | MAP_EFLG_SPAD | MAP_EFLG_WAYUP)
  427.           && !(control_status & CONTROL_UP))
  428.       {
  429.          /* FIXME what? */
  430.          E_RICK_STRST (E_RICK_STCLIMB);
  431.          return;
  432.       }
  433.  
  434.       if (!(env1 & (MAP_EFLG_SOLID | MAP_EFLG_SPAD | MAP_EFLG_WAYUP))
  435.           || (env1 & MAP_EFLG_WAYUP))
  436.       {
  437.          /* ok to move, save */
  438.          E_RICK_ENT.y = y;
  439.  
  440.          if (env1 & MAP_EFLG_LETHAL)
  441.          {
  442.             e_rick_gozombie ();
  443.             return;
  444.          }
  445.  
  446.          if (!(env1 & (MAP_EFLG_VERT | MAP_EFLG_CLIMB)))
  447.          {
  448.             /* reached end of climb zone */
  449.             offsy = (control_status & CONTROL_UP) ? -0x0300 : 0x0100;
  450.  
  451.             if (control_status & CONTROL_UP)
  452.                syssnd_play (WAV_JUMP, 1);
  453.  
  454.             E_RICK_STRST (E_RICK_STCLIMB);
  455.             return;
  456.          }
  457.       }
  458.    }
  459.  
  460.    if (control_status & (CONTROL_LEFT | CONTROL_RIGHT))
  461.    {
  462.       /* left-right: calc new x and test environment */
  463.       if (control_status & CONTROL_LEFT)
  464.       {
  465.          x = E_RICK_ENT.x - 0x02;
  466.  
  467.          if (x < 0)
  468.          {
  469.             /* (i.e. negative) prev submap */
  470.             game_chsm = TRUE;
  471.  
  472.             /*6dbd = 0x00;*/
  473.             E_RICK_ENT.x = 0xe2;
  474.             return;
  475.          }
  476.       }
  477.       else
  478.       {
  479.          x = E_RICK_ENT.x + 0x02;
  480.  
  481.          if (x >= 0xe8)
  482.          {
  483.             /* next submap */
  484.             game_chsm = TRUE;
  485.  
  486.             /*6dbd = 0x01;*/
  487.             E_RICK_ENT.x = 0x04;
  488.             return;
  489.          }
  490.       }
  491.  
  492.       u_envtest (x, E_RICK_ENT.y, (U8) E_RICK_STTST (E_RICK_STCRAWL), &env0, &env1);
  493.  
  494.       if (env1 & (MAP_EFLG_SOLID|MAP_EFLG_SPAD))
  495.          return;
  496.  
  497.       E_RICK_ENT.x = x;
  498.  
  499.       if (env1 & MAP_EFLG_LETHAL)
  500.       {
  501.          e_rick_gozombie ();
  502.          return;
  503.       }
  504.  
  505.       if (env1 & (MAP_EFLG_VERT | MAP_EFLG_CLIMB))
  506.          return;
  507.  
  508.       E_RICK_STRST (E_RICK_STCLIMB);
  509.  
  510.       if (control_status & CONTROL_UP)
  511.          offsy = -0x0300;
  512.    }
  513. }
  514.  
  515.  
  516. /*
  517.  * Action function for e_rick
  518.  *
  519.  * ASM 12CA
  520.  */
  521. void e_rick_action (U8 e)
  522. {
  523.    static U8 stopped = FALSE; /* is this the most elegant way? */
  524.  
  525.    e_rick_action2 ();
  526.  
  527.    scrawl = E_RICK_STTST (E_RICK_STCRAWL);
  528.  
  529.    if E_RICK_STTST (E_RICK_STZOMBIE)
  530.       return;
  531.  
  532.    /*
  533.     * set sprite
  534.     */
  535.    if (E_RICK_STTST (E_RICK_STSTOP))
  536.    {
  537.       E_RICK_ENT.sprite = (game_dir ? 0x17 : 0x0B);
  538.  
  539.       if (!stopped)
  540.       {
  541.          syssnd_play (WAV_STICK, 1);
  542.          stopped = TRUE;
  543.       }
  544.       return;
  545.    }
  546.  
  547.    stopped = FALSE;
  548.  
  549.    if (E_RICK_STTST (E_RICK_STSHOOT))
  550.    {
  551.       E_RICK_ENT.sprite = (game_dir ? 0x16 : 0x0A);
  552.       return;
  553.    }
  554.  
  555.    if (E_RICK_STTST (E_RICK_STCLIMB))
  556.    {
  557.       E_RICK_ENT.sprite = (((E_RICK_ENT.x ^ E_RICK_ENT.y) & 0x04) ? 0x18 : 0x0c);
  558.       seq = (seq + 1) & 0x03;
  559.  
  560.       if (seq == 0)
  561.          syssnd_play (WAV_WALK, 1);
  562.  
  563.       return;
  564.    }
  565.  
  566.    if (E_RICK_STTST(E_RICK_STCRAWL))
  567.    {
  568.       E_RICK_ENT.sprite = (game_dir ? 0x13 : 0x07);
  569.  
  570.       if (E_RICK_ENT.x & 0x04)
  571.          E_RICK_ENT.sprite++;
  572.  
  573.       seq = (seq + 1) & 0x03;
  574.  
  575.       if (seq == 0)
  576.          syssnd_play (WAV_CRAWL, 1);
  577.  
  578.       return;
  579.    }
  580.  
  581.    if (E_RICK_STTST (E_RICK_STJUMP))
  582.    {
  583.       E_RICK_ENT.sprite = (game_dir ? 0x15 : 0x06);
  584.       return;
  585.    }
  586.  
  587.    seq++;
  588.  
  589.    if (seq >= 0x14)
  590.    {
  591.       syssnd_play (WAV_WALK, 1);
  592.       seq = 0x04;
  593.    }
  594.    else if (seq == 0x0C)
  595.       syssnd_play (WAV_WALK, 1);
  596.  
  597.    E_RICK_ENT.sprite = (seq >> 2) + 1 + (game_dir ? 0x0c : 0x00);
  598. }
  599.  
  600.  
  601. /*
  602.  * Save status
  603.  *
  604.  * ASM part of 0x0BBB
  605.  */
  606. void e_rick_save (void)
  607. {
  608.    save_x = E_RICK_ENT.x;
  609.    save_y = E_RICK_ENT.y;
  610.    save_crawl = E_RICK_STTST (E_RICK_STCRAWL);
  611.  
  612.    /* FIXME
  613.     * save_C0 = E_RICK_ENT.b0C;
  614.     * plus some 6DBC stuff?
  615.     */
  616. }
  617.  
  618.  
  619. /*
  620.  * Restore status
  621.  *
  622.  * ASM part of 0x0BDC
  623.  */
  624. void e_rick_restore (void)
  625. {
  626.    E_RICK_ENT.x = save_x;
  627.    E_RICK_ENT.y = save_y;
  628.    E_RICK_ENT.front = FALSE;
  629.  
  630.    if (save_crawl)
  631.       E_RICK_STSET (E_RICK_STCRAWL);
  632.    else
  633.       E_RICK_STRST (E_RICK_STCRAWL);
  634.  
  635.    /* FIXME
  636.     * E_RICK_ENT.b0C = save_C0;
  637.     * plus some 6DBC stuff?
  638.     */
  639. }
  640.