Subversion Repositories Games.Rick Dangerous

Rev

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