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_them.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_them.h"
  18.  
  19. #include "e_rick.h"
  20. #include "e_bomb.h"
  21. #include "e_bullet.h"
  22. #include "maps.h"
  23. #include "util.h"
  24.  
  25. #define TYPE_1A (0x00)
  26. #define TYPE_1B (0xff)
  27.  
  28.  
  29. /*
  30.  * public vars
  31.  */
  32. U32 e_them_rndseed = 0;
  33.  
  34.  
  35. /*
  36.  * local vars
  37.  */
  38. static U16 e_them_rndnbr = 0;
  39.  
  40.  
  41. /*
  42.  * Check if entity boxtests with a lethal e_them i.e. something lethal
  43.  * in slot 0 and 4 to 8.
  44.  *
  45.  * ASM 122E
  46.  *
  47.  * e: entity slot number.
  48.  * ret: TRUE/boxtests, FALSE/not
  49.  */
  50. U8 u_themtest (U8 e)
  51. {
  52.    U8 i;
  53.  
  54.    if ((ent_ents[0].n & ENT_LETHAL) && u_boxtest (e, 0))
  55.       return TRUE;
  56.  
  57.    for (i = 4; i < 9; i++)
  58.       if ((ent_ents[i].n & ENT_LETHAL) && u_boxtest (e, i))
  59.          return TRUE;
  60.  
  61.    return FALSE;
  62. }
  63.  
  64.  
  65. /*
  66.  * Go zombie
  67.  *
  68.  * ASM 237B
  69.  */
  70. void e_them_gozombie (U8 e)
  71. {
  72. #define offsx c1
  73.    ent_ents[e].n = 0x47;   /* zombie entity */
  74.    ent_ents[e].front = TRUE;
  75.    ent_ents[e].offsy = -0x0400;
  76.    syssnd_play(WAV_DIE, 1);
  77.    game_score += 50;
  78.    if (ent_ents[e].flags & ENT_FLG_ONCE)
  79.    {
  80.       /* make sure entity won't be activated again */
  81.       map_marks[ent_ents[e].mark].ent |= MAP_MARK_NACT;
  82.    }
  83.    ent_ents[e].offsx = (ent_ents[e].x >= 0x80 ? -0x02 : 0x02);
  84. #undef offsx
  85. }
  86.  
  87.  
  88. /*
  89.  * Action sub-function for e_them _t1a and _t1b
  90.  *
  91.  * Those two types move horizontally, and fall if they have to.
  92.  * Type 1a moves horizontally over a given distance and then
  93.  * u-turns and repeats; type 1b is more subtle as it does u-turns
  94.  * in order to move horizontally towards rick.
  95.  *
  96.  * ASM 2242
  97.  */
  98. void e_them_t1_action2 (U8 e, U8 type)
  99. {
  100. #define offsx c1
  101. #define step_count c2
  102.    U32 i;
  103.    S16 x, y;
  104.    U8 env0, env1;
  105.  
  106.    /* by default, try vertical move. calculate new y */
  107.    i = (ent_ents[e].y << 8) + ent_ents[e].offsy + ent_ents[e].ylow;
  108.    y = (S16) (i >> 8);
  109.  
  110.    /* deactivate if outside vertical boundaries */
  111.    /* no need to test zero since e_them _t1a/b don't go up */
  112.    /* FIXME what if they got scrolled out ? */
  113.    if (y > 0x140)
  114.    {
  115.       ent_ents[e].n = 0;
  116.       return;
  117.    }
  118.  
  119.    /* test environment */
  120.    u_envtest (ent_ents[e].x, y, FALSE, &env0, &env1);
  121.  
  122.    if (!(env1 & (MAP_EFLG_VERT | MAP_EFLG_SOLID | MAP_EFLG_SPAD | MAP_EFLG_WAYUP)))
  123.    {
  124.       /* vertical move possible: falling */
  125.       if (env1 & MAP_EFLG_LETHAL)
  126.       {
  127.          /* lethal entities kill e_them */
  128.          e_them_gozombie (e);
  129.          return;
  130.       }
  131.  
  132.       /* save, cleanup and return */
  133.       ent_ents[e].y = y;
  134.       ent_ents[e].ylow = (U8) i;
  135.       ent_ents[e].offsy += 0x0080;
  136.  
  137.       if (ent_ents[e].offsy > 0x0800)
  138.          ent_ents[e].offsy = 0x0800;
  139.  
  140.       return;
  141.    }
  142.  
  143.    /* vertical move not possible. calculate new sprite */
  144.    ent_ents[e].sprite = ent_ents[e].sprbase + ent_sprseq[(ent_ents[e].x & 0x1c) >> 3] + (ent_ents[e].offsx < 0 ? 0x03 : 0x00);
  145.  
  146.    /* reset offsy */
  147.    ent_ents[e].offsy = 0x0080;
  148.  
  149.    /* align to ground */
  150.    ent_ents[e].y &= 0xfff8;
  151.    ent_ents[e].y |= 0x0003;
  152.  
  153.    /* latency: if not zero then decrease and return */
  154.    if (ent_ents[e].latency > 0)
  155.    {
  156.       ent_ents[e].latency--;
  157.       return;
  158.    }
  159.  
  160.    /* horizontal move. calculate new x */
  161.    if (ent_ents[e].offsx == 0)   /* not supposed to move -> don't */
  162.       return;
  163.  
  164.    x = ent_ents[e].x + ent_ents[e].offsx;
  165.    if (ent_ents[e].x < 0x01 || ent_ents[e].x > 0xe8)
  166.    {
  167.       /* deactivate if reaching horizontal boundaries */
  168.       ent_ents[e].n = 0;
  169.       return;
  170.    }
  171.  
  172.    /* test environment */
  173.    u_envtest (x, ent_ents[e].y, FALSE, &env0, &env1);
  174.  
  175.    if (env1 & (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP))
  176.    {
  177.       /* horizontal move not possible: u-turn and return */
  178.       ent_ents[e].step_count = 0;
  179.       ent_ents[e].offsx = -ent_ents[e].offsx;
  180.       return;
  181.    }
  182.  
  183.    /* horizontal move possible */
  184.    if (env1 & MAP_EFLG_LETHAL)
  185.    {
  186.       /* lethal entities kill e_them */
  187.       e_them_gozombie (e);
  188.       return;
  189.    }
  190.  
  191.    /* save */
  192.    ent_ents[e].x = x;
  193.  
  194.    /* depending on type, */
  195.    if (type == TYPE_1B)
  196.    {
  197.       /* set direction to move horizontally towards rick */
  198.       if ((ent_ents[e].x & 0x1e) != 0x10) /* prevents too frequent u-turns */
  199.          return;
  200.       ent_ents[e].offsx = (ent_ents[e].x < E_RICK_ENT.x) ? 0x02 : -0x02;
  201.       return;
  202.    }
  203.    else
  204.    {
  205.       /* set direction according to step counter */
  206.       ent_ents[e].step_count++;
  207.  
  208.       /* FIXME why trig_x (b16) ?? */
  209.       if ((ent_ents[e].trig_x >> 1) > ent_ents[e].step_count)
  210.          return;
  211.    }
  212.  
  213.    /* type is 1A and step counter reached its limit: u-turn */
  214.    ent_ents[e].step_count = 0;
  215.    ent_ents[e].offsx = -ent_ents[e].offsx;
  216. #undef offsx
  217. #undef step_count
  218. }
  219.  
  220.  
  221. /*
  222.  * ASM 21CF
  223.  */
  224. void e_them_t1_action (U8 e, U8 type)
  225. {
  226.    e_them_t1_action2 (e, type);
  227.  
  228.    /* lethal entities kill them */
  229.    if (u_themtest (e))
  230.    {
  231.       e_them_gozombie (e);
  232.       return;
  233.    }
  234.  
  235.    /* bullet kills them */
  236.    if (E_BULLET_ENT.n && u_fboxtest (e, (S16) (E_BULLET_ENT.x + (e_bullet_offsx < 0 ? 0 : 0x18)), E_BULLET_ENT.y))
  237.    {
  238.       E_BULLET_ENT.n = 0;
  239.       e_them_gozombie (e);
  240.       return;
  241.    }
  242.  
  243.    /* bomb kills them */
  244.    if (e_bomb_lethal && e_bomb_hit (e))
  245.    {
  246.       e_them_gozombie (e);
  247.       return;
  248.    }
  249.  
  250.    if (E_RICK_STTST (E_RICK_STZOMBIE))
  251.       return;
  252.  
  253.    /* rick stops them */
  254.    if (E_RICK_STTST (E_RICK_STSTOP) && u_fboxtest (e, e_rick_stop_x, e_rick_stop_y))
  255.       ent_ents[e].latency = 0x14;
  256.  
  257.    /* they kill rick */
  258.    if (e_rick_boxtest (e))
  259.       e_rick_gozombie ();
  260. }
  261.  
  262.  
  263. /*
  264.  * Action function for e_them _t1a type (stays within boundaries)
  265.  *
  266.  * ASM 2452
  267.  */
  268. void e_them_t1a_action (U8 e)
  269. {
  270.    e_them_t1_action (e, TYPE_1A);
  271. }
  272.  
  273.  
  274. /*
  275.  * Action function for e_them _t1b type (runs for rick)
  276.  *
  277.  * ASM 21CA
  278.  */
  279. void e_them_t1b_action (U8 e)
  280. {
  281.    e_them_t1_action (e, TYPE_1B);
  282. }
  283.  
  284.  
  285. /*
  286.  * Action function for e_them _z (zombie) type
  287.  *
  288.  * ASM 23B8
  289.  */
  290. void e_them_z_action (U8 e)
  291. {
  292. #define offsx c1
  293.    U32 i;
  294.  
  295.    /* calc new sprite */
  296.    ent_ents[e].sprite = ent_ents[e].sprbase + ((ent_ents[e].x & 0x04) ? 0x07 : 0x06);
  297.  
  298.    /* calc new y */
  299.    i = (ent_ents[e].y << 8) + ent_ents[e].offsy + ent_ents[e].ylow;
  300.  
  301.    /* deactivate if out of vertical boundaries */
  302.    if (ent_ents[e].y < 0 || ent_ents[e].y > 0x0140)
  303.    {
  304.       ent_ents[e].n = 0;
  305.       return;
  306.    }
  307.  
  308.    /* save */
  309.    ent_ents[e].offsy += 0x0080;
  310.    ent_ents[e].ylow = (U8) i;
  311.    ent_ents[e].y = (S16) (i >> 8);
  312.  
  313.    /* calc new x */
  314.    ent_ents[e].x += ent_ents[e].offsx;
  315.  
  316.    /* must stay within horizontal boundaries */
  317.    if (ent_ents[e].x < 0)
  318.       ent_ents[e].x = 0;
  319.    if (ent_ents[e].x > 0xe8)
  320.       ent_ents[e].x = 0xe8;
  321. #undef offsx
  322. }
  323.  
  324.  
  325. /*
  326.  * Action sub-function for e_them _t2.
  327.  *
  328.  * Must document what it does.
  329.  *
  330.  * ASM 2792
  331.  */
  332. void e_them_t2_action2 (U8 e)
  333. {
  334. #define flgclmb c1
  335. #define offsx c2
  336.    U32 i;
  337.    S16 x, y, yd;
  338.    U8 env0, env1;
  339.  
  340.    /*
  341.     * vars required by the Black Magic (tm) performance at the
  342.     * end of this function.
  343.     */
  344.    static U16 bx;
  345.    static U8 *bl = (U8 *)&bx;
  346.    static U8 *bh = (U8 *)&bx + 1;
  347.    static U16 cx;
  348.    static U8 *cl = (U8 *)&cx;
  349.    static U8 *ch = (U8 *)&cx + 1;
  350.    static U16 *sl = (U16 *)&e_them_rndseed;
  351.    static U16 *sh = (U16 *)&e_them_rndseed + 2;
  352.  
  353.    /*sys_printf("e_them_t2 ------------------------------\n");*/
  354.  
  355.    /* latency: if not zero then decrease */
  356.    if (ent_ents[e].latency > 0)
  357.       ent_ents[e].latency--;
  358.  
  359.    /* climbing? */
  360.    if (ent_ents[e].flgclmb != TRUE)
  361.       goto climbing_not;
  362.  
  363.    /* CLIMBING */
  364.  
  365.    /*sys_printf("e_them_t2 climbing\n");*/
  366.  
  367.    /* latency: if not zero then return */
  368.    if (ent_ents[e].latency > 0)
  369.       return;
  370.  
  371.    /* calc new sprite */
  372.    ent_ents[e].sprite = ent_ents[e].sprbase + 0x08 + (((ent_ents[e].x ^ ent_ents[e].y) & 0x04) ? 1 : 0);
  373.  
  374.    /* reached rick's level? */
  375.    if ((ent_ents[e].y & 0xfe) != (E_RICK_ENT.y & 0xfe))
  376.       goto ymove;
  377.  
  378. xmove:
  379.       /* calc new x and test environment */
  380.       ent_ents[e].offsx = (ent_ents[e].x < E_RICK_ENT.x) ? 0x02 : -0x02;
  381.       x = ent_ents[e].x + ent_ents[e].offsx;
  382.       u_envtest (x, ent_ents[e].y, FALSE, &env0, &env1);
  383.  
  384.       if (env1 & (MAP_EFLG_SOLID | MAP_EFLG_SPAD | MAP_EFLG_WAYUP))
  385.          return;
  386.  
  387.       if (env1 & MAP_EFLG_LETHAL)
  388.       {
  389.          e_them_gozombie(e);
  390.          return;
  391.       }
  392.  
  393.       ent_ents[e].x = x;
  394.  
  395.       if (env1 & (MAP_EFLG_VERT | MAP_EFLG_CLIMB))   /* still climbing */
  396.          return;
  397.  
  398.       goto climbing_not;   /* not climbing anymore */
  399.  
  400. ymove:
  401.       /* calc new y and test environment */
  402.       yd = ent_ents[e].y < E_RICK_ENT.y ? 0x02 : -0x02;
  403.       y = ent_ents[e].y + yd;
  404.  
  405.       if (y < 0 || y > 0x0140)
  406.       {
  407.          ent_ents[e].n = 0;
  408.          return;
  409.       }
  410.  
  411.       u_envtest (ent_ents[e].x, y, FALSE, &env0, &env1);
  412.  
  413.       if (env1 & (MAP_EFLG_SOLID | MAP_EFLG_SPAD | MAP_EFLG_WAYUP))
  414.       {
  415.          if (yd < 0)
  416.             goto xmove;   /* can't go up */
  417.          else
  418.             goto climbing_not;   /* can't go down */
  419.       }
  420.  
  421.       /* can move */
  422.       ent_ents[e].y = y;
  423.  
  424.       if (env1 & (MAP_EFLG_VERT | MAP_EFLG_CLIMB))   /* still climbing */
  425.          return;
  426.  
  427.       /* NOT CLIMBING */
  428.  
  429. climbing_not:
  430.       /*sys_printf ("e_them_t2 climbing NOT\n");*/
  431.  
  432.       ent_ents[e].flgclmb = FALSE;   /* not climbing */
  433.  
  434.       /* calc new y (falling) and test environment */
  435.       i = (ent_ents[e].y << 8) + ent_ents[e].offsy + ent_ents[e].ylow;
  436.       y = (S16) (i >> 8);
  437.  
  438.       u_envtest (ent_ents[e].x, y, FALSE, &env0, &env1);
  439.  
  440.       if (!(env1 & (MAP_EFLG_SOLID | MAP_EFLG_SPAD | MAP_EFLG_WAYUP)))
  441.       {
  442.          /*sys_printf ("e_them_t2 y move OK\n");*/
  443.          /* can go there */
  444.          if (env1 & MAP_EFLG_LETHAL)
  445.          {
  446.             e_them_gozombie (e);
  447.             return;
  448.          }
  449.  
  450.          if (y > 0x0140)
  451.          {
  452.             /* deactivate if outside */
  453.             ent_ents[e].n = 0;
  454.             return;
  455.          }
  456.  
  457.          if (!(env1 & MAP_EFLG_VERT))
  458.          {
  459.             /* save */
  460.             ent_ents[e].y = y;
  461.             ent_ents[e].ylow = (U8) i;
  462.             ent_ents[e].offsy += 0x0080;
  463.  
  464.             if (ent_ents[e].offsy > 0x0800)
  465.                ent_ents[e].offsy = 0x0800;
  466.  
  467.             return;
  468.          }
  469.  
  470.          if (((ent_ents[e].x & 0x07) == 0x04) && (y < E_RICK_ENT.y))
  471.          {
  472.             /*sys_printf ("e_them_t2 climbing00\n");*/
  473.             ent_ents[e].flgclmb = TRUE;   /* climbing */
  474.             return;
  475.          }
  476.       }
  477.  
  478.       /*sys_printf("e_them_t2 ymove nok or ...\n");*/
  479.       /* can't go there, or ... */
  480.       ent_ents[e].y = (ent_ents[e].y & 0xf8) | 0x03;   /* align to ground */
  481.       ent_ents[e].offsy = 0x0100;
  482.       if (ent_ents[e].latency != 00)
  483.          return;
  484.  
  485.       if ((env1 & MAP_EFLG_CLIMB) && ((ent_ents[e].x & 0x0e) == 0x04) && (ent_ents[e].y > E_RICK_ENT.y))
  486.       {
  487.          /*sys_printf ("e_them_t2 climbing01\n");*/
  488.          ent_ents[e].flgclmb = TRUE;   /* climbing */
  489.          return;
  490.       }
  491.  
  492.       /* calc new sprite */
  493.       ent_ents[e].sprite = ent_ents[e].sprbase + ent_sprseq[(ent_ents[e].offsx < 0 ? 4 : 0) + ((ent_ents[e].x & 0x0e) >> 3)];
  494.       /*sys_printf ("e_them_t2 sprite %02x\n", ent_ents[e].sprite);*/
  495.  
  496.  
  497.       /* */
  498.       if (ent_ents[e].offsx == 0)
  499.          ent_ents[e].offsx = 2;
  500.  
  501.       x = ent_ents[e].x + ent_ents[e].offsx;
  502.  
  503.       /*sys_printf ("e_them_t2 xmove x=%02x\n", x);*/
  504.  
  505.       if (x < 0xe8)
  506.       {
  507.          u_envtest (x, ent_ents[e].y, FALSE, &env0, &env1);
  508.          if (!(env1 & (MAP_EFLG_VERT | MAP_EFLG_SOLID | MAP_EFLG_SPAD | MAP_EFLG_WAYUP)))
  509.          {
  510.             ent_ents[e].x = x;
  511.  
  512.             if ((x & 0x1e) != 0x08)
  513.                return;
  514.  
  515.             /*
  516.              * Black Magic (tm)
  517.              *
  518.              * this is obviously some sort of randomizer to define a direction
  519.              * for the entity. it is an exact copy of what the assembler code
  520.              * does but I can't explain.
  521.              */
  522.             bx = e_them_rndnbr + *sh + *sl + 0x0d;
  523.             cx = *sh;
  524.             *bl ^= *ch;
  525.             *bl ^= *cl;
  526.             *bl ^= *bh;
  527.             e_them_rndnbr = bx;
  528.  
  529.             ent_ents[e].offsx = (*bl & 0x01) ? -0x02 : 0x02;
  530.  
  531.             /* back to normal */
  532.  
  533.             return;
  534.          }
  535.       }
  536.  
  537.       /* U-turn */
  538.       /*sys_printf ("e_them_t2 u-turn\n");*/
  539.       if (ent_ents[e].offsx == 0)
  540.          ent_ents[e].offsx = 2;
  541.       else
  542.          ent_ents[e].offsx = -ent_ents[e].offsx;
  543. #undef offsx
  544. }
  545.  
  546.  
  547. /*
  548.  * Action function for e_them _t2 type
  549.  *
  550.  * ASM 2718
  551.  */
  552. void e_them_t2_action (U8 e)
  553. {
  554.    e_them_t2_action2 (e);
  555.  
  556.    /* they kill rick */
  557.    if (e_rick_boxtest (e))
  558.       e_rick_gozombie ();
  559.  
  560.    /* lethal entities kill them */
  561.    if (u_themtest (e))
  562.    {
  563.       e_them_gozombie (e);
  564.       return;
  565.    }
  566.  
  567.    /* bullet kills them */
  568.    if (E_BULLET_ENT.n && u_fboxtest (e, (S16) (E_BULLET_ENT.x + (e_bullet_offsx < 0 ? 00 : 0x18)), E_BULLET_ENT.y))
  569.    {
  570.       E_BULLET_ENT.n = 0;
  571.       e_them_gozombie (e);
  572.       return;
  573.    }
  574.  
  575.    /* bomb kills them */
  576.    if (e_bomb_lethal && e_bomb_hit (e))
  577.    {
  578.       e_them_gozombie (e);
  579.       return;
  580.    }
  581.  
  582.    /* rick stops them */
  583.    if (E_RICK_STTST (E_RICK_STSTOP) && u_fboxtest (e, e_rick_stop_x, e_rick_stop_y))
  584.       ent_ents[e].latency = 0x14;
  585. }
  586.  
  587.  
  588. /*
  589.  * Action sub-function for e_them _t3
  590.  *
  591.  * FIXME always starts asleep??
  592.  *
  593.  * Waits until triggered by something, then execute move steps from
  594.  * ent_mvstep with sprite from ent_sprseq. When done, either restart
  595.  * or disappear.
  596.  *
  597.  * Not always lethal ... but if lethal, kills rick.
  598.  *
  599.  * ASM: 255A
  600.  */
  601. void e_them_t3_action2 (U8 e)
  602. {
  603. #define sproffs c1
  604. #define step_count c2
  605.    U8 i;
  606.    S16 x, y;
  607.  
  608.    while (1)
  609.    {
  610.       /* calc new sprite */
  611.       i = ent_sprseq[ent_ents[e].sprbase + ent_ents[e].sproffs];
  612.       if (i == 0xff)
  613.          i = ent_sprseq[ent_ents[e].sprbase];
  614.       ent_ents[e].sprite = i;
  615.  
  616.       if (ent_ents[e].sproffs != 0)
  617.       {
  618.          /* awake */
  619.  
  620.          /* rotate sprseq */
  621.          if (ent_sprseq[ent_ents[e].sprbase + ent_ents[e].sproffs] != 0xff)
  622.             ent_ents[e].sproffs++;
  623.          if (ent_sprseq[ent_ents[e].sprbase + ent_ents[e].sproffs] == 0xff)
  624.             ent_ents[e].sproffs = 1;
  625.  
  626.          if (ent_ents[e].step_count < ent_mvstep[ent_ents[e].step_no].count)
  627.          {
  628.             /*
  629.              * still running this step: try to increment x and y while
  630.              * checking that they remain within boudaries. if so, return.
  631.              * else switch to next step.
  632.              */
  633.             ent_ents[e].step_count++;
  634.             x = ent_ents[e].x + ent_mvstep[ent_ents[e].step_no].dx;
  635.  
  636.             /* check'n save */
  637.             if (x > 0 && x < 0xe8)
  638.             {
  639.                ent_ents[e].x = x;
  640.                /*FIXME*/
  641.                /*
  642.                y = ent_mvstep[ent_ents[e].step_no].dy;
  643.                if (y < 0)
  644.                y += 0xff00;
  645.                y += ent_ents[e].y;
  646.                */
  647.                y = ent_ents[e].y + ent_mvstep[ent_ents[e].step_no].dy;
  648.                if (y > 0 && y < 0x0140)
  649.                {
  650.                   ent_ents[e].y = y;
  651.                   return;
  652.                }
  653.             }
  654.          }
  655.  
  656.          /*
  657.           * step is done, or x or y is outside boundaries. try to
  658.           * switch to next step
  659.           */
  660.          ent_ents[e].step_no++;
  661.          if (ent_mvstep[ent_ents[e].step_no].count != 0xff)
  662.             ent_ents[e].step_count = 0; // there is a next step: init and loop
  663.          else
  664.          {
  665.             /* there is no next step: restart or deactivate */
  666.             if (!E_RICK_STTST (E_RICK_STZOMBIE) && !(ent_ents[e].flags & ENT_FLG_ONCE))
  667.             {
  668.                /* loop this entity */
  669.                ent_ents[e].sproffs = 0;
  670.                ent_ents[e].n &= ~ENT_LETHAL;
  671.  
  672.                if (ent_ents[e].flags & ENT_FLG_LETHALR)
  673.                   ent_ents[e].n |= ENT_LETHAL;
  674.  
  675.                ent_ents[e].x = ent_ents[e].xsave;
  676.                ent_ents[e].y = ent_ents[e].ysave;
  677.  
  678.                if (ent_ents[e].y < 0 || ent_ents[e].y > 0x140)
  679.                {
  680.                   ent_ents[e].n = 0;
  681.                   return;
  682.                }
  683.             }
  684.             else
  685.             {
  686.                /* deactivate this entity */
  687.                ent_ents[e].n = 0;
  688.                return;
  689.             }
  690.          }
  691.       }
  692.       else
  693.       {
  694.          /* ent_ents[e].sprseq1 == 0 -- waiting */
  695.  
  696.          /* ugly GOTOs */
  697.  
  698.          /* reacts to rick */
  699.          if (ent_ents[e].flags & ENT_FLG_TRIGRICK)
  700.          {
  701.             /* wake up if triggered by rick */
  702.             if (u_trigbox (e, (S16) (E_RICK_ENT.x + 0x0C), (S16) (E_RICK_ENT.y + 0x0A)))
  703.                goto wakeup;
  704.          }
  705.  
  706.          /* reacts to rick "stop" */
  707.          if (ent_ents[e].flags & ENT_FLG_TRIGSTOP)
  708.          {
  709.             /* wake up if triggered by rick "stop" */
  710.             if (E_RICK_STTST(E_RICK_STSTOP) && u_trigbox (e, e_rick_stop_x, e_rick_stop_y))
  711.                goto wakeup;
  712.          }
  713.  
  714.          /* reacts to bullets */
  715.          if (ent_ents[e].flags & ENT_FLG_TRIGBULLET)
  716.          {
  717.             /* wake up if triggered by bullet */
  718.             if (E_BULLET_ENT.n && u_trigbox(e, e_bullet_xc, e_bullet_yc))
  719.             {
  720.                E_BULLET_ENT.n = 0;
  721.                goto wakeup;
  722.             }
  723.          }
  724.  
  725.          /* reacts to bombs */
  726.          if (ent_ents[e].flags & ENT_FLG_TRIGBOMB)
  727.          {
  728.             /* wake up if triggered by bomb */
  729.             if (e_bomb_lethal && u_trigbox(e, e_bomb_xc, e_bomb_yc))
  730.                goto wakeup;
  731.          }
  732.  
  733.          /* not triggered: keep waiting */
  734.          return;
  735.  
  736.          /* something triggered the entity: wake up */
  737.          /* initialize step counter */
  738. wakeup:
  739.          if (E_RICK_STTST (E_RICK_STZOMBIE))
  740.             return;
  741.  
  742.          /*
  743.           * FIXME the sound should come from a table, there are 10 of them
  744.           * but I dont have the table yet. must rip the data off the game...
  745.           * FIXME is it 8 of them, not 10?
  746.           * FIXME testing below...
  747.           */
  748.          if ((ent_ents[e].trigsnd & 0x1F) != 0)
  749.             syssnd_play(WAV_ENTITY[(ent_ents[e].trigsnd & 0x1F) - 0x14], 1);
  750.  
  751.          ent_ents[e].n &= ~ENT_LETHAL;
  752.  
  753.          if (ent_ents[e].flags & ENT_FLG_LETHALI)
  754.             ent_ents[e].n |= ENT_LETHAL;
  755.  
  756.          ent_ents[e].sproffs = 1;
  757.          ent_ents[e].step_count = 0;
  758.          ent_ents[e].step_no = ent_ents[e].step_no_i;
  759.          return;
  760.       }
  761.    }
  762. #undef step_count
  763. }
  764.  
  765.  
  766. /*
  767.  * Action function for e_them _t3 type
  768.  *
  769.  * ASM 2546
  770.  */
  771. void e_them_t3_action (U8 e)
  772. {
  773.    e_them_t3_action2 (e);
  774.  
  775.    /* if lethal, can kill rick */
  776.    if ((ent_ents[e].n & ENT_LETHAL) && !E_RICK_STTST (E_RICK_STZOMBIE) && e_rick_boxtest (e))
  777.       e_rick_gozombie (); // CALL 1130
  778. }
  779.