Guest

Untitled

By: a guest on Mar 21st, 2010  |  syntax: C  |  size: 31.93 KB  |  hits: 87  |  expires: Never
download  |  raw  |  embed  |  report abuse
Copied
  1.  
  2. #define __CKCM__
  3. #define COMP_BORLAND
  4.  
  5. #include "include\keen1.h";
  6. #include "include\game.h";
  7. #include "include\sprites2.h";
  8. #include "spacer.dat";
  9.  
  10. short CM_draw_level(short levelnum) {
  11.        
  12.         short i,j, st_x, st_y;
  13.         Sprite *sp1, *sp2;
  14.        
  15.         num_sprites = 1;
  16.         num_bodies = 0;
  17.         sprite_sync = 0;
  18.         ticks = ticks_sync = 0;
  19.         keen_invincible = god_mode = 0;
  20.         level_finished = 0;
  21.         keen_facing = 1;
  22.        
  23.         // update CM_init_level with keen variables later
  24.         sprites[0].type = sprites[0].active = 1;
  25.         sprites[0].think = TH_keen_ground;
  26.         sprites[0].contact = CO_keen;
  27.         sprites[0].velX = sprites[0].velY = 0;
  28.         sprites[0].frame = 0;
  29.        
  30.         CM_init_level(levelnum);
  31.        
  32.         // set screen position
  33.         scrollX = sprites[0].posX - 0xA000;
  34.         scrollY = sprites[0].posY - 0x5000;
  35.         if (scrollX < scrollX_min)
  36.                 scrollX = scrollX_min;
  37.                
  38.         if (scrollY < scrollY_min)
  39.                 scrollY = scrollY_min;
  40.        
  41.         if (scrollX > scrollX_max)
  42.                 scrollX = scrollX_max;
  43.                
  44.         if (scrollY > scrollY_max)
  45.                 scrollY = scrollY_max;
  46.        
  47.         // draw screen
  48.         sync_drawing();
  49.         fade_out();
  50.         lights = 1;
  51.         clear_overlay();
  52.         draw_screen();
  53.         draw_screen();
  54.         fade_in();
  55.  
  56.        
  57.         scrollX_T = map2tile(scrollX);
  58.         scrollY_T = map2tile(scrollY);
  59.        
  60.         // level loop
  61.         do {
  62.                
  63.                 sync_drawing();
  64.                 memcpy(&input_new, handle_ctrl(&input_new, 1), sizeof(Input));
  65.                                
  66.                 // think loop
  67.                 for (i = 0; i < num_sprites; i++) {
  68.                        
  69.                         // don't update if sprite ID = 0;
  70.                         if(sprites[i].type != 0) {
  71.                                                                
  72.                                 memcpy(&temp_sprite, &sprites[i], sizeof(Sprite));
  73.                                 if (!CM_sprite_active_screen()) {
  74.                                         CM_update_sprite_hitbox();
  75.                                         temp_sprite.delX = temp_sprite.delY = 0;
  76.                                         temp_sprite.think();
  77.                                         temp_sprite.posX += temp_sprite.delX;
  78.                                         temp_sprite.posY += temp_sprite.delY;
  79.                                         CM_update_sprite_hitbox();
  80.                                 }
  81.                                
  82.                                 memcpy(&sprites[i], &temp_sprite, sizeof(Sprite));
  83.                         }
  84.                 }
  85.                
  86.                 CM_do_scrolling();
  87.                                
  88.                 // collision loop
  89.                 for (i = 0, sp1 = sprites; i < num_sprites; i++, sp1++) {
  90.                         if(sp1->type && sp1->active) {
  91.                                 for(j = i + 1, sp2 = sp1+1; j < num_sprites; j++, sp2++) {
  92.                                         if(sp2->type && sp2->active) {
  93.                                                 if (CM_detect_sprite_col(sp1, sp2)) {
  94.                                                         sp1->contact(sp1, sp2);
  95.                                                         sp2->contact(sp2, sp1);
  96.                                                 }
  97.                                         }
  98.                                 }
  99.                         }
  100.                 }
  101.                        
  102.                 scrollX_T = map2tile(scrollX);
  103.                 scrollY_T = map2tile(scrollY);
  104.                
  105.                 // draw sprites
  106.                 for(i = 0; i < num_sprites; i++)
  107.                         if(sprites[i].type && sprites[i].type)
  108.                                 draw_sprite_at(sprites[i].posX, sprites[i].posY, sprites[i].frame);
  109.                
  110.                 // keen/tile collisions        
  111.                 CM_keen_bgtile_col();
  112.                
  113.                 // bodies
  114.                 for (i = 0; i < num_bodies; i++)
  115.                         if (bodies[i].type)
  116.                                 bodies[i].think(&bodies[i]);
  117.                                
  118.                 //
  119.                 draw_screen();
  120.                 memcpy(&input_old, &input_new, sizeof(Input));
  121.                 handle_cheat_keys();
  122.                 if (handle_global_keys())
  123.                         ticks_sync = ticks;
  124.                
  125.                 if (quit_to_title)
  126.                         return LEVEL_DIE;
  127.                        
  128.                
  129.         } while (level_finished == LEVEL_DIE && sprites[0].type != 0);
  130.        
  131.  
  132.         finish_cur_sound();
  133.         fade_out();
  134.        
  135.         for (i = 0; i < 4; i++) {
  136.                 keen_gp.stuff[5+i] = 0;
  137.         }
  138.        
  139.         if (level_finished == LEVEL_DIE) {
  140.                
  141.                 // remove parts
  142.         }
  143.        
  144.         return level_finished;
  145.        
  146. }
  147.  
  148. void CM_init_level(short levelnum) {
  149.         short x, y, t;
  150.         load_level_data(levelnum);
  151.        
  152.         for(y = 0; y < map_height_T; y++) {
  153.        
  154.                 for(x = 0; x < map_width_T; x++) {
  155.                        
  156.                         t = map_data_sprites[y * map_width_T + x];
  157.                         switch (t) {
  158.                         /* all the sprites     
  159.                                 case 1:
  160.                                         add_janitor(x, y);
  161.                                         break;
  162.                                        
  163.                                 case 2:
  164.                                 case 3:
  165.                                 case 4:
  166.                                 case 5:
  167.                         */
  168.                                 case 255:
  169.                                         sprites[0].posX = tile2map(x);
  170.                                         sprites[0].posY = tile2map(y);
  171.                                         break;
  172.                                 default:
  173.                                         break;
  174.                         }
  175.                                
  176.                 }
  177.                
  178.         }
  179.         return;
  180. }
  181.  
  182. Sprite *CM_add_sprite(void) {
  183.        
  184.         int i;
  185.         Sprite *sp;
  186.        
  187.         for(i = 1, sp = sprites + 1;
  188.             i < num_sprites && sp->type != 0;
  189.             i++, sp++);
  190.            
  191.         if(i >= num_sprites) {
  192.                 num_sprites++;
  193.         }
  194.        
  195.         memset(sp, 0, sizeof(Sprite));
  196.         sp->think = TH_nop;
  197.         sp->contact = CO_nop;
  198.         sp->active = 1;
  199.        
  200.         return sp;
  201. }
  202.  
  203.  
  204. Body *CM_add_body(void) {
  205.        
  206.         int i;
  207.         Body *bp;
  208.        
  209.         for(i = 0, bp = bodies+1;
  210.             i < num_bodies && bp->type != 0;
  211.             i++, bp++);
  212.            
  213.         if(i >= num_sprites) {
  214.                 num_sprites++;
  215.         }
  216.        
  217.         memset(bp, 0, sizeof(Body));
  218.         bp->think = BO_nop;
  219.         return bp;
  220. }
  221.  
  222.  
  223. short CM_detect_sprite_col(Sprite *s1, Sprite *s2) {
  224.        
  225.         if (!s1->type || s2 -> type)
  226.                 return 0;
  227.        
  228.         if (s1->boxX2 < s2->boxX1 ||
  229.          s1->boxX1 > s2->boxX2 ||
  230.          s1->boxY2 < s2->boxY1 ||
  231.          s1->boxY1 > s2->boxY2 )
  232.                 return 0;
  233.                
  234.         return 1;
  235.        
  236. }
  237.  
  238. void CM_update_sprite_hitbox(void) {
  239.         short f = (temp_sprite.frame * 4) + ((temp_sprite.posX >> 9) % 4);
  240.         void __far* fp = Masked_Entries + f;
  241.         movedata(FP_SEG(fp), FP_OFF(fp), _DS, (short)&temp_MSE, sizeof(MaskedSpriteEntry));
  242.         temp_sprite.boxX1 = (long)temp_MSE.hitbox_L + temp_sprite.posX;
  243.         temp_sprite.boxX2 = (long)temp_MSE.hitbox_R + temp_sprite.posX;
  244.         temp_sprite.boxY1 = (long)temp_MSE.hitbox_U + temp_sprite.posY;
  245.         temp_sprite.boxY2 = (long)temp_MSE.hitbox_D + temp_sprite.posY;
  246.         return;
  247. }
  248.  
  249. void CM_update_sprite_hitbox_wmap(Sprite *sp) {
  250.         memcpy(&temp_sprite, sp, sizeof(Sprite));
  251.         CM_update_sprite_hitbox();
  252.         memcpy(sp, &temp_sprite, sizeof(Sprite));
  253.         return;
  254. }
  255.  
  256. void CM_move_horz(short max, short min, short dv) {
  257.         int i;
  258.         for (i = 1; i <= sprite_sync; i++) {
  259.                 temp_sprite.velX += dv;
  260.                 if (temp_sprite.velX > max)
  261.                         temp_sprite.velX = max;
  262.                 else if (temp_sprite.velX < min)
  263.                         temp_sprite.velX = min;
  264.                
  265.                 if (i != sprite_sync)
  266.                         temp_sprite.delX += temp_sprite.velX;
  267.         }
  268.         return;
  269. }
  270.  
  271. void CM_move_vert(short max, short min, short dv) {
  272.         int i;
  273.         for(i = 1; i <= sprite_sync; i++) {
  274.                 temp_sprite.velY += dv;
  275.                 if (temp_sprite.velY > max)
  276.                         temp_sprite.velY = max;
  277.                 else if (temp_sprite.velY < min)
  278.                         temp_sprite.velY = min;
  279.                 if (i != sprite_sync)
  280.                         temp_sprite.delY += temp_sprite.velY;
  281.         }
  282.         return;
  283. }
  284.  
  285. short CM_compute_sprite_delta(void) {
  286.         temp_sprite.delX += sprite_sync * temp_sprite.velX;
  287.         temp_sprite.delY += sprite_sync * temp_sprite.velY;
  288.         asm { DB 9Ah, 0F0h, 0Dh, 0BEh, 0EFh} //ckpatch far addr over FOODBEEF
  289.         return _AX;
  290. }
  291.  
  292. short CM_sprite_active_screen(void) {
  293.  
  294.         short tx, ty;
  295.        
  296.         tx = map2tile(temp_sprite.posX);
  297.         ty = map2tile(temp_sprite.posY);
  298.        
  299.         if (temp_sprite.posY < 0)
  300.                 temp_sprite.posY = 0;
  301.                
  302.         if (temp_sprite.posX < map_width &&
  303.          temp_sprite.posX >= 0 &&
  304.          temp_sprite.posY <= map_height) {
  305.                 if (tx >= (scrollX_T - 8) &&
  306.                 ty >= (scrollY_T - 8) &&
  307.                 tx <= (scrollX_T +28) &&
  308.                 ty <= (scrollY_T +14) )
  309.                         return 0;
  310.                
  311.                 if (temp_sprite.type < 9)
  312.                         temp_sprite.active = 0;
  313.                 else
  314.                         temp_sprite.type = 0;
  315.         }              
  316.        
  317.         return 1;
  318. }
  319.  
  320. // If sprite exits screen, returns edge name
  321. short CM_check_ceiling(void) {
  322.  
  323.         short ret = 0;
  324.  
  325.         if (temp_sprite.posX > ceilingX) {
  326.                 temp_sprite.delX = temp_sprite.velX = 0;
  327.                 temp_sprite.posX = ceilingX;
  328.                 ret |= EDGE_R;
  329.         }
  330.        
  331.         if (temp_sprite.posX < scrollX_min + 8) {
  332.                 temp_sprite.delX = temp_sprite.velX = 0;
  333.                 temp_sprite.posX = scrollX_min + 8;
  334.                 ret |= EDGE_L;
  335.         }
  336.        
  337.         if (temp_sprite.posY < scrollY_min + 8) {
  338.                 temp_sprite.delY = temp_sprite.velY = 0;
  339.                 temp_sprite.posY = scrollY_min + 8;
  340.                 ret |= EDGE_U;
  341.         }
  342.  
  343.         if (temp_sprite.posY > ceilingY) {
  344.                 temp_sprite.delY = temp_sprite.velY = 0;
  345.                 temp_sprite.posY = ceilingY;
  346.                 ret |= EDGE_D;
  347.         }
  348.        
  349.         return ret;
  350. }
  351.  
  352.  
  353. void CM_do_scrolling(void) {
  354.        
  355.         short dx = sprites[0].delX;
  356.         short dy = sprites[0].delY;
  357.        
  358.         if(sprites[0].think != TH_keen_exit && sprites[0].think != TH_keen_dead) {
  359.  
  360.                 // scroll left
  361.                 if (dx > 0 && (sprites[0].posX - scrollX > 0xB000)) {
  362.                                 scrollX += (long)dx;
  363.                                 if (scrollX > scrollX_max)
  364.                                         scrollX = scrollX_max;
  365.                 }
  366.                
  367.                 //right
  368.                 if (dx < 0 && (sprites[0].posX - scrollX < 0x9000)) {
  369.                                 scrollX += (long)dx;
  370.                                 if (scrollX < scrollX_min)
  371.                                         scrollX = scrollX_min;
  372.                 }
  373.                
  374.                 //down
  375.                 if (dy > 0 && (sprites[0].posY - scrollY > 0x7000)) {
  376.                                 scrollY += (long)dy;
  377.                                 if (scrollY > scrollY_max)
  378.                                         scrollY = scrollY_max;
  379.                 }
  380.                
  381.                 // up
  382.                 if (dy < 0 && (sprites[0].posY - scrollY < 0x3000)) {
  383.                                 scrollY += (long)dy;
  384.                                 if (scrollY < scrollY_min)
  385.                                         scrollY = scrollY_min;
  386.                 }
  387.         }
  388.        
  389.         return;
  390.        
  391. }
  392.  
  393. void CM_change_palette(char *pal) {
  394.        
  395.         delay(1);
  396.         asm {
  397.                 mov AX, DS
  398.                 mov ES, AX
  399.                 mov DX, pal
  400.                 mov AX, 1002h
  401.                 int 10h
  402.         }
  403.         return;
  404.        
  405. }
  406.  
  407. void CM_toggle_lights(void) {
  408.        
  409.         if(input_new.but2 && !input_old.but2) {
  410.                 set_cur_sound(25);
  411.                 if (lights != 0) {
  412.                         CM_change_palette(&palette_1);
  413.                         lights = 0;
  414.                 } else {
  415.                         CM_change_palette(&palette_3);
  416.                         lights = 1;
  417.                 }
  418.         }
  419.        
  420.         return;
  421. }
  422.  
  423. void CM_shake_screen(void) {
  424.        
  425.         int i;
  426.         long sx = scrollX;
  427.         long sy = scrollY;
  428.        
  429.         for (i = 0; i < 80; i++) {
  430.                 sync_drawing();
  431.                 scrollX = sx + (calc_jump_height(64) - 32) * 256;
  432.                 scrollY = sy + (calc_jump_height(64) - 32) * 256;
  433.                 draw_sprite_at(temp_sprite.posX, temp_sprite.posY, temp_sprite.frame);
  434.                 draw_screen();
  435.         }
  436.        
  437.         draw_box_opening2(5,1);
  438.         draw_string(aOops_);
  439.         delay(100);
  440.         level_finished = LEVEL_TANTALUS;
  441.         return;
  442. }
  443.  
  444.  
  445. // switch links to a bridge info tile in the sprite map
  446. // sprite plane: bridge_info (bits C to F) is type 1
  447. //                               bits 0 to 9 are replacement tile ID (0 thru 1023)
  448. //                               bits A,B specify bridge direction
  449. // tile_plane:   switch on (25):
  450. //                               switch off (26):
  451.  
  452. void CM_toggle_bridge(short tx, short ty) {
  453.        
  454.         short n,tp,sp, li,lx, ly;
  455.         Body *bp;
  456.        
  457.         n = ty * map_width_T + tx;
  458.         tp = map_data_tiles[n];
  459.         sp = map_data_sprites[n]; // the pointer tile
  460.         lx = (sp & 0xFF) + tx;  // linked tile coords
  461.         ly = ((sp & 0xFF00) >> 8)+ ty;
  462.         li = map_data_sprites[ly * map_width_T + lx];
  463.        
  464.         // return if link does not point to bridge control
  465.         if ((sp >> 12) != 1) return;
  466.        
  467.         // spawn new bridge controller
  468.         bp = CM_add_body();
  469.         bp->posX = lx; // link coordinates
  470.         bp->posY = ly;
  471.         bp->type = 1; // type 1 = bridge
  472.         bp->time = 0;
  473.         bp->variant = ((li >> 10) % 4); // direction
  474.         bp->varB = n; // pointer tile in sprite plane
  475.         bp->varC = li & 0x03FF; //replacement tile
  476.         bp->think = BO_bridge;
  477.                        
  478.         // change tile_plane
  479.         if (TI_Type[tp] & 1)
  480.                 map_data_tiles[n]--; // on --> off
  481.         else
  482.                 map_data_tiles[n]++; // off --> on
  483.         return;
  484. }
  485.  
  486. void BO_bridge(Body *bp) {
  487.        
  488.         short lx, ly, n;
  489.        
  490.         bp->time += sprite_sync;
  491.         if (bp->time <= 30) return;
  492.         bp->time = 0;
  493.        
  494.         //move to next square
  495.         switch (bp->variant) {
  496.                 case 0: bp->posY--; break; // up
  497.                 case 1: bp->posX++; break; // right
  498.                 case 2: bp->posY++; break; // down
  499.                 case 3: bp->posX--; break; // left
  500.                 default: break;
  501.         }
  502.        
  503.         //update link tile pointer
  504.         lx = bp->varB % map_width_T;
  505.         ly = bp->varB / 13;
  506.         map_data_sprites[bp->varB] = (bp->posY - ly << 8) | (bp->posX - lx);
  507.                
  508.         //if square is bridge control destroy body; else place tile
  509.         n = bp->posY * map_width_T + bp->posX;
  510.         if (map_data_sprites[n] >> 12 == 1) {
  511.                 bp->type = 0;
  512.                 num_bodies--;
  513.         } else {
  514.                 map_data_tiles[n] = bp->varC;
  515.         }
  516.        
  517.         return;
  518. }
  519.  
  520. void CM_do_fall(void) {
  521.         CM_move_vert(200, -400, 3);
  522.         return;
  523. }
  524.  
  525.  
  526. // Keen
  527. // Common
  528. void CM_keen_walk(short dv) {
  529.         CM_move_horz(120, -120,dv);
  530.         return;
  531. }
  532.  
  533. void CM_keen_pogo(void) {
  534.         CM_move_vert(200, -200, -1);
  535.         return;
  536. }
  537.  
  538. void CM_keen_bgtile_col(void) {
  539.        
  540.         short tx1, tx2, ty1, ty2, tx, ty, ti, tc;
  541.         register Sprite *k;
  542.        
  543.         keen_switch = 0;
  544.         k = sprites;
  545.        
  546.         if (k->think == TH_keen_dead)
  547.                 return;
  548.        
  549.         tx1 = map2tile(k->boxX1);
  550.         tx2 = map2tile(k->boxX2);
  551.         ty1 = map2tile(k->boxY1);
  552.         ty2 = map2tile(k->boxY2);
  553.        
  554.         for (tx = tx1; tx <= tx2; tx++) {
  555.                 for (ty = ty1; ty <= ty2; ty++) {
  556.                         tc = ty * map_width_T + tx;
  557.                         ti = TI_Type[map_data_tiles[tc]];
  558.                         switch (ti) {
  559.                                 case 0:
  560.                                         break;
  561.                                
  562.                                 // enemies
  563.                                 case 1:
  564.                                         CM_kill_keen();
  565.                                         break;
  566.                                 //doors
  567.                                 case 2:
  568.                                 case 3:
  569.                                 case 4:
  570.                                 case 5:
  571.                                         if (keen_gp.stuff[5+(ti-1)]) { open_door(tx, ty); }
  572.                                         else if (k->delX > 0) { k->posX &= 0xFFFFF000L; }
  573.                                         else { k->posX = (k->posX + 0x1000) & 0xFFFFF000L; }
  574.                                         break;
  575.                                
  576.                                 // score items
  577.                                 case 6:
  578.                                 case 7:
  579.                                 case 8:
  580.                                 case 9:
  581.                                 case 10:
  582.                                         add_score(points_tbl[ti - 6]);
  583.                                         set_cur_sound(9);
  584.                                         goto replacetile;
  585.                                         break;
  586.                                
  587.                                 // parts
  588.                                 case 11:
  589.                                 case 12:
  590.                                 case 13:
  591.                                 case 14:
  592.                                         keen_gp.stuff[ti - 10] = 1;
  593.                                         add_score(10000);
  594.                                         set_cur_sound(11);
  595.                                         goto replacetile;
  596.                                         break;
  597.                                
  598.                                 // raygun
  599.                                 case 28:
  600.                                         keen_gp.ammo -= 4;
  601.                                 case 15:       
  602.                                         keen_gp.ammo += 5;
  603.                                         set_cur_sound(10);
  604.                                         goto replacetile;
  605.                                         break;
  606.                                 // pogo
  607.                                 case 16:
  608.                                         break;
  609.                        
  610.                                 // exit
  611.                                 case 17:
  612.                                         if (k->think == TH_keen_ground) {
  613.                                                 k->think = TH_keen_exit;
  614.                                                 k->contact = CO_nop;
  615.                                                 k->varA = tx;
  616.                                                 k->varB = ty;
  617.                                                 set_cur_sound(15);
  618.                                         }
  619.                                         break;
  620.                                
  621.                                 // keycards
  622.                                 case 18:
  623.                                 case 19:
  624.                                 case 20:       
  625.                                 case 21:
  626.                                         keen_gp.stuff[5+ti-17] = 1;
  627.                                         set_cur_sound(32);
  628.                                         goto replacetile;
  629.                                         break;
  630.                                
  631.                                 // statue
  632.                                 case 22:
  633.                                         statue_message();
  634.                                         goto replacetile;
  635.                                         break;
  636.                                        
  637.                                 // lightswitch
  638.                                 case 23:
  639.                                         keen_switch = 1;
  640.                                         CM_toggle_lights();
  641.                                         break;
  642.                                
  643.                                 // teleporter
  644.                                 case 24:
  645.                                         level_finished = LEVEL_SECRET;
  646.                                         break;
  647.                                        
  648.                                 case 25:
  649.                                 case 26:
  650.                                         keen_switch = 1;
  651.                                         CM_toggle_bridge(tx, ty);
  652.                                         break;
  653.                                        
  654.                                
  655.                                 default:
  656.                                         break;
  657.                                        
  658.                                 replacetile:
  659.                                         map_data_tiles[tc] = (map_data_tiles[tc] / 13) * 13;
  660.                                         break;
  661.                         }
  662.                 }
  663.         }
  664.         return;
  665. }
  666.  
  667. // Thinks
  668. // varA temp vel x
  669.  
  670. // varB   temp vel y
  671. // varC   temp frame
  672.  
  673. // varD = airborne:  1 if keen airborne, 0 otherwise
  674.  
  675. void TH_keen_ground(void) {
  676.        
  677.         short x, y, vs, csd;
  678.         char t, t_sl, t_bl;
  679.        
  680.         x = map2tile(((temp_sprite.boxX1 + temp_sprite.boxX2) >> 1));
  681.         y = map2tile((temp_sprite.boxY2 + 1));
  682.         t = TI_UEdge[map_data_tiles[y * map_width_T + x]];
  683.         t_bl = t & 3; // blocking
  684.         t_sl = t >> 4; // slope info
  685.        
  686.         /* movement from input (slippery and blocking only) */
  687.         if (t_bl != 3) {
  688.        
  689.                 switch (input_new.dir) {
  690.                        
  691.                         case 1:
  692.                         case 2:
  693.                         case 3:
  694.                                 CM_keen_walk(2);
  695.                                 if (temp_sprite.velX < 0) goto decelerate;
  696.                                 break;
  697.  
  698.                         case 5:
  699.                         case 6:
  700.                         case 7:
  701.                                 CM_keen_walk(-2);
  702.                                 if (temp_sprite.velX > 0) goto decelerate;
  703.                                 break;
  704.        
  705.                         // decelerate if on normal
  706.                         decelerate:
  707.                         case 0:
  708.                         case 4:
  709.                         case 8:
  710.                                 if (t_bl <= 1) {
  711.                                        
  712.                                         if(temp_sprite.velX > 0) {
  713.                                                 CM_keen_walk(-3);
  714.                                                 if (temp_sprite.velX < 0)
  715.                                                         temp_sprite.velX = 0;
  716.                                         }
  717.                                        
  718.                                         if (temp_sprite.velX < 0) {
  719.                                                 CM_keen_walk(3);
  720.                                                 if (temp_sprite.velX > 0)
  721.                                                         temp_sprite.velX = 0;
  722.                                         }
  723.                                 }
  724.                                 break;
  725.                         default: break;
  726.                 }
  727.                
  728.                 // scale velocity if moving uphill
  729.                 if ( (t_sl & 8) && // is sloped
  730.                         ( ((temp_sprite.velX > 0) &&  (t_sl & 4)) || // move right positive slope
  731.                           ((temp_sprite.velX < 0) && !(t_sl & 4)) ) ) // move left negative slope
  732.                 {
  733.                         switch (t_sl & 3) {
  734.                                 case 0: vs = 25; break; // 1/1
  735.                                 case 1: vs = 28; break; // 1/2
  736.                                 case 2: vs = 30; break; // 1/4
  737.                                 case 3: vs = 31; break; // 1/8th (unused)
  738.                                 default: vs = 32; break; // ??
  739.                         }
  740.                         temp_sprite.velX = (temp_sprite.velX * vs) / 32;
  741.                 }
  742.         }      
  743.                
  744.         /* movement from icy/slippery slopes */
  745.         if ( (t_bl >= 2) && (t_sl & 8) ) {
  746.                
  747.         // increase velocity in downhill direction
  748.                 switch (t_sl & 3) {
  749.                         case 0: vs = 36; break; // 1/1
  750.                         case 1: vs = 35; break; // 1/2
  751.                         case 2: vs = 34; break; // 1/4
  752.                         case 3: vs = 33; break; // 1/8th (unused)
  753.                         default: vs = 32; break; // ??
  754.                 }
  755.                 temp_sprite.velX = (temp_sprite.velX * vs) / 32;
  756.         }
  757.                
  758.         /* frames */
  759.        
  760.         // standing l/r
  761.         if (keen_facing > 0)
  762.                 temp_sprite.frame = 0;
  763.         else
  764.                 temp_sprite.frame = 4;
  765.        
  766.         // looking up down
  767.         switch (input_new.dir) {
  768.                
  769.                 case 0:
  770.                 case 4:
  771.                         temp_sprite.think = TH_keen_look;
  772.                         temp_sprite.time = 0;
  773.                         break;
  774.                
  775.                 //if no dir input, but on slippery, advance frames
  776.                 case 8:
  777.                         if (t_bl != 2) break;
  778.                                        
  779.                 case 1:
  780.                 case 2:
  781.                 case 3:
  782.                 case 5:
  783.                 case 6:
  784.                 case 7:
  785.                         if (t_bl <= 2)
  786.                                 temp_sprite.frame += (ticks >> 4) & 3;
  787.                        
  788.                         if (temp_sprite.velX != 0)
  789.                                 keen_facing = temp_sprite.velX;
  790.                        
  791.                                 break;
  792.                
  793.                 default:
  794.                 break;
  795.                
  796.         }
  797.                
  798.         // sound
  799.         if ( (temp_sprite.velX != 0) && ((ticks >> 4) & 1) && (t_bl < 3) ) {
  800.                         if ((ticks >> 5) & 1)
  801.                                 set_cur_sound(30);
  802.                         else
  803.                                 set_cur_sound(4);
  804.         }
  805.        
  806.         // adjust position
  807.         CM_do_fall();
  808.         csd = CM_compute_sprite_delta();
  809.         if (CM_check_ceiling() & EDGE_D)
  810.                 CM_kill_keen_temp();
  811.        
  812.         // wall blokcing sound
  813.         if ( ((csd & EDGE_L) || (csd & EDGE_R)) && ((ticks >> 4) & 1) )
  814.                 set_cur_sound(5);
  815.        
  816.         // falling
  817.         if ( !(csd & EDGE_U) && !temp_sprite.varD ) {
  818.                 temp_sprite.think = TH_keen_jump_air;
  819.                 set_cur_sound(27);
  820.        
  821.         } else {
  822.                
  823.                 // jump
  824.                 if (input_new.but1) {
  825.                        
  826.                         temp_sprite.varA = temp_sprite.velX;
  827.                         temp_sprite.velX = temp_sprite.varB = temp_sprite.time = 0;
  828.                        
  829.                         if (keen_facing > 0)
  830.                                 temp_sprite.varC = 8; //jumpright1
  831.                         else
  832.                                 temp_sprite.varC = 14; //jumpleft1
  833.                
  834.                         temp_sprite.think = TH_keen_jump_ground;
  835.                 }
  836.                
  837.                 // pogo
  838.                 if (input_new.but2 && !input_old.but2 && !keen_switch && keen_gp.stuff[3]) {
  839.                         temp_sprite.varA = temp_sprite.velX;
  840.                         temp_sprite.time = temp_sprite.velX = 0;
  841.                         temp_sprite.think = TH_keen_pogo_ground;
  842.                 }
  843.                        
  844.                 if (input_new.but3 && !input_old.but3) {
  845.                         temp_sprite.think = TH_keen_shoot_ground;
  846.                         temp_sprite.velX = temp_sprite.time = temp_sprite.varC = 0;
  847.                 }
  848.                
  849.                 if (temp_sprite.varD)
  850.                         temp_sprite.varD = 0;
  851.                
  852.                
  853.         }
  854.        
  855.         return;
  856. }
  857.  
  858.        
  859. void TH_keen_jump_ground(void) {
  860.  
  861.         // update frame
  862.         temp_sprite.frame = temp_sprite.varC + (temp_sprite.time / 6);
  863.        
  864.         // increase temp velY
  865.         if (input_new.but1)
  866.                 temp_sprite.varB = sprite_sync * 6 + temp_sprite.varB;
  867.         else if (temp_sprite.time < 12)
  868.                 temp_sprite.time = 24 - temp_sprite.time;
  869.        
  870.         // increase     temp velX
  871.         switch (input_new.dir) {
  872.                
  873.                 case 1:
  874.                 case 2:
  875.                 case 3:
  876.                         temp_sprite.varA += (sprite_sync << 1);
  877.                         if (temp_sprite.varA > 120)
  878.                                 temp_sprite.varA  = 120;
  879.                         break;
  880.                
  881.                 case 5:
  882.                 case 6:
  883.                 case 7:
  884.                         temp_sprite.varA -= (sprite_sync << 1);
  885.                         if (temp_sprite.varA < -120)
  886.                                 temp_sprite.varA  = -120;
  887.                         break;
  888.                
  889.                 default:
  890.                         break;
  891.         }
  892.  
  893.        
  894.         temp_sprite.velX = 0;
  895.         temp_sprite.time += sprite_sync;
  896.        
  897.         if (temp_sprite.time >= 36) {
  898.                 temp_sprite.think = TH_keen_jump_air;
  899.                 temp_sprite.velY -= temp_sprite.varB;
  900.                 temp_sprite.velX = temp_sprite.varA;
  901.                 set_cur_sound(6);
  902.         }
  903.        
  904.         CM_do_fall();
  905.         CM_compute_sprite_delta();
  906.         if (CM_check_ceiling() & EDGE_D)
  907.                 CM_kill_keen_temp();
  908.        
  909.  
  910.         if (input_new.but3 && !input_old.but3) {
  911.                 temp_sprite.think = TH_keen_shoot_ground;
  912.                 temp_sprite.velX = temp_sprite.time = temp_sprite.varC = 0;
  913.         }
  914.        
  915.         return;
  916. }
  917.  
  918.  
  919. void TH_keen_jump_air(void) {
  920.        
  921.         short csd;
  922.        
  923.         // handle movement
  924.         switch (input_new.dir) {
  925.                
  926.                 case 1:
  927.                 case 2:
  928.                 case 3:
  929.                         CM_keen_walk(2);
  930.                         if (temp_sprite.velX < 0)
  931.                                 goto decelerate;
  932.                         break;
  933.                
  934.                 case 5:
  935.                 case 6:
  936.                 case 7:
  937.                         CM_keen_walk(-2);
  938.                         if (temp_sprite.velX > 0)
  939.                                 goto decelerate;
  940.                         break;
  941.                        
  942.                 decelerate:
  943.                 default:
  944.                 case 0:
  945.                 case 4:
  946.                 case 8:
  947.                
  948.                 if (temp_sprite.velX > 0) {
  949.                         CM_keen_walk(-1);
  950.                         if (temp_sprite.velX < 0)
  951.                                 temp_sprite.velX = 0;
  952.                 } else if (temp_sprite.velX < 0) {
  953.                         CM_keen_walk(1);
  954.                         if (temp_sprite.velX > 0)
  955.                                 temp_sprite.velX = 0;
  956.                 }
  957.         }
  958.        
  959.        
  960.         if (keen_facing > 0)
  961.                 temp_sprite.frame = 13; //jumpright
  962.         else
  963.                 temp_sprite.frame = 19; //jumpleft
  964.        
  965.         if (temp_sprite.velX != 0)
  966.                 keen_facing = temp_sprite.velX;
  967.                
  968.         CM_do_fall();
  969.         csd = CM_compute_sprite_delta();
  970.        
  971.         if ((csd & EDGE_L) || (csd & EDGE_R))
  972.                 if ((ticks >> 4) & 1)
  973.                         set_cur_sound(5);
  974.        
  975.         if (csd & EDGE_U && temp_sprite.velY >= 0) {
  976.                 temp_sprite.think = TH_keen_ground;
  977.                 set_cur_sound(7);
  978.         } else {
  979.                 if (csd & EDGE_D)
  980.                         set_cur_sound(21);
  981.                
  982.                 if (CM_check_ceiling() & EDGE_D)
  983.                         CM_kill_keen_temp();
  984.        
  985.                 if (input_new.but2 & !input_old.but2 && !keen_switch && keen_gp.stuff[3])
  986.                         temp_sprite.think = TH_keen_pogo_air;
  987.                
  988.         }
  989.        
  990.         if (input_new.but3 && !input_old.but3) {
  991.                 temp_sprite.think = TH_keen_shoot_air;
  992.                 temp_sprite.velX = temp_sprite.time = temp_sprite.varC = 0;
  993.         }
  994.        
  995.         return;
  996. }
  997.  
  998. void TH_keen_pogo_ground(void) {
  999.        
  1000.        
  1001.         temp_sprite.velX = temp_sprite.delX = 0;
  1002.         temp_sprite.time += sprite_sync;
  1003.        
  1004.         if (temp_sprite.time < 22)  {
  1005.  
  1006.                 if (keen_facing > 0)
  1007.                         temp_sprite.frame = 25;
  1008.                 else
  1009.                         temp_sprite.frame = 27;
  1010.                        
  1011.         } else {
  1012.                
  1013.                 temp_sprite.think = TH_keen_pogo_air;
  1014.                 temp_sprite.velY -= 200;
  1015.                 temp_sprite.velX = temp_sprite.varA;
  1016.                 set_cur_sound(6);
  1017.         }
  1018.        
  1019.         if (input_new.but2 && !input_old.but2)
  1020.                 temp_sprite.think = TH_keen_ground;
  1021.                        
  1022.        
  1023.         if (input_new.but3 && !input_old.but3) {
  1024.                 temp_sprite.think = TH_keen_shoot_ground;
  1025.                 temp_sprite.velX = temp_sprite.time = temp_sprite.varC = 0;
  1026.         }
  1027.        
  1028.         CM_compute_sprite_delta();
  1029.         temp_sprite.varD = 0;  // not airborne
  1030.        
  1031.         return;
  1032. }
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039. void TH_keen_pogo_air(void) {
  1040.        
  1041.         int csd = 0;
  1042.        
  1043.         // do movement
  1044.         switch (input_new.dir) {
  1045.                 case 1:
  1046.                 case 2:
  1047.                 case 3:
  1048.                         CM_keen_walk(1);
  1049.                         break;
  1050.                
  1051.                 case 5:
  1052.                 case 6:
  1053.                 case 7:
  1054.                         CM_keen_walk(-1);
  1055.                         break;
  1056.                
  1057.                 default:
  1058.                         break;
  1059.         }      
  1060.        
  1061.        
  1062.         if (input_new.but1 && temp_sprite.velY < 0)
  1063.                 CM_keen_pogo();
  1064.        
  1065.         if (god_mode && input_new.but1)
  1066.                 temp_sprite.velY = -200;
  1067.        
  1068.         if (temp_sprite.velX != 0)
  1069.                 keen_facing = temp_sprite.velX;
  1070.                
  1071.         if (keen_facing >= 0)
  1072.                 temp_sprite.frame = 24;
  1073.         else
  1074.                 temp_sprite.frame = 26;
  1075.                
  1076.         CM_do_fall();
  1077.         csd = CM_compute_sprite_delta();
  1078.        
  1079.         // wall blocking sound
  1080.         if ((csd & EDGE_L) || (csd & EDGE_R))
  1081.                 if ((ticks >> 4) & 1)
  1082.                         set_cur_sound(5);
  1083.                        
  1084.         if (csd & EDGE_U && temp_sprite.velY >= 0) {
  1085.                 temp_sprite.think = TH_keen_pogo_ground;
  1086.                 temp_sprite.varA = temp_sprite.velX;
  1087.                 temp_sprite.time = temp_sprite.velX = 0;
  1088.         }
  1089.        
  1090.         if (csd & EDGE_D)
  1091.                 set_cur_sound(21);
  1092.                
  1093.         if (CM_check_ceiling() & EDGE_D)
  1094.                 CM_kill_keen_temp();
  1095.        
  1096.        
  1097.         if (input_new.but2 && !input_old.but2 && !keen_switch)
  1098.                 temp_sprite.think = TH_keen_jump_air;
  1099.        
  1100.                
  1101.         if (input_new.but3 && !input_old.but3) {
  1102.                 temp_sprite.think = TH_keen_shoot_air;
  1103.                 temp_sprite.velX = temp_sprite.time = temp_sprite.varC = 0;
  1104.         }
  1105.        
  1106.         if (temp_sprite.varD !=0)
  1107.                 temp_sprite.varD = 0;
  1108.                
  1109.         return;
  1110. }
  1111.  
  1112. // varC: if set, cannot fire; if reset, can fire
  1113. void TH_keen_shoot_ground(void) {
  1114.        
  1115.         short d;
  1116.         long x, y;
  1117.        
  1118.         temp_sprite.time += sprite_sync;
  1119.         if (!temp_sprite.varC) {
  1120.                
  1121.                         x = temp_sprite.posX;
  1122.                         y = temp_sprite.posY + 0x800;
  1123.                         d = input_new.dir;
  1124.                        
  1125.                         switch (d) {
  1126.                                
  1127.                                 case 1:
  1128.                                 case 3:
  1129.                                 case 2:
  1130.                                
  1131.                                 case 5:
  1132.                                 case 7:
  1133.                                 case 6:
  1134.                                         break;
  1135.                                
  1136.                                 case 8:
  1137.                                         if (keen_facing > 0)
  1138.                                                 d = 2;
  1139.                                         else
  1140.                                                 d = 6;
  1141.                                         break; 
  1142.                                
  1143.                                 default:
  1144.                                 case 4:
  1145.                                         d = -1;
  1146.                                         break;
  1147.                         }
  1148.                                
  1149.                         if (d >= 0) {
  1150.                                 temp_sprite.frame = 50 + d;
  1151.                                 if (keen_gp.ammo > 0) {
  1152.                                         ADD_stunner(x,y,d);
  1153.                                         set_cur_sound(12);
  1154.                                         keen_gp.ammo--;
  1155.                                 } else {
  1156.                                         set_cur_sound(36);
  1157.                                 }
  1158.                         }
  1159.  
  1160.                 temp_sprite.varC = 1;
  1161.         }
  1162.        
  1163.         if (temp_sprite.time > 30 && !input_new.but3)
  1164.                 temp_sprite.think = TH_keen_ground;
  1165.        
  1166.         if (temp_sprite.velX > 0) {
  1167.                 CM_keen_walk(-1);
  1168.                 if (temp_sprite.velX < 0)
  1169.                         temp_sprite.velX = 0;
  1170.         }
  1171.        
  1172.         if (temp_sprite.velX < 0) {
  1173.                 CM_keen_walk(1);
  1174.                 if (temp_sprite.velX > 0)
  1175.                         temp_sprite.velX = 0;
  1176.         }
  1177.        
  1178.         CM_do_fall();
  1179.         CM_compute_sprite_delta();
  1180.         if (CM_check_ceiling() & EDGE_D)
  1181.                 CM_kill_keen_temp();
  1182.        
  1183.         return;
  1184. }
  1185.  
  1186.  
  1187.  
  1188. // varC: if set, cannot fire; if reset, can fire
  1189. void TH_keen_shoot_air(void) {
  1190.        
  1191.         short d;
  1192.         long x, y;
  1193.        
  1194.         temp_sprite.time += sprite_sync;
  1195.         if (!temp_sprite.varC) {
  1196.                
  1197.                         x = temp_sprite.posX;
  1198.                         y = temp_sprite.posY + 0x800;
  1199.                         d = input_new.dir;
  1200.                        
  1201.                         switch (d) {
  1202.                                
  1203.                                 case 0:
  1204.                                
  1205.                                 case 1:
  1206.                                 case 3:
  1207.                                 case 2:
  1208.                                
  1209.                                 case 4:
  1210.                                
  1211.                                 case 5:
  1212.                                 case 7:
  1213.                                 case 6:
  1214.                                         break;
  1215.                                
  1216.                                 default:
  1217.                                 case 8:
  1218.                                         if (keen_facing > 0)
  1219.                                                 d = 2;
  1220.                                         else
  1221.                                                 d = 6;
  1222.                                         break; 
  1223.                         }
  1224.                                
  1225.                         if (d >= 0) {
  1226.                                 temp_sprite.frame = 60 + d;
  1227.                                 if (keen_gp.ammo > 0) {
  1228.                                         ADD_stunner(x,y,d);
  1229.                                         set_cur_sound(12);
  1230.                                         keen_gp.ammo--;
  1231.                                 } else {
  1232.                                         set_cur_sound(36);
  1233.                                 }
  1234.                         }
  1235.  
  1236.                 temp_sprite.varC = 1;
  1237.         }
  1238.        
  1239.         if (temp_sprite.time > 30 && !input_new.but3)
  1240.                 temp_sprite.think = TH_keen_jump_air;
  1241.        
  1242.  
  1243.         CM_do_fall();
  1244.         CM_compute_sprite_delta();
  1245.         if (CM_check_ceiling() & EDGE_D)
  1246.                 CM_kill_keen_temp();
  1247.        
  1248.                
  1249.         return;
  1250. }
  1251.  
  1252.  
  1253. void TH_keen_look(void) {
  1254.  
  1255.         temp_sprite.time += sprite_sync;
  1256.        
  1257.         if (input_new.dir == 0 && input_old.dir == 0) {
  1258.                 temp_sprite.frame = 10;
  1259.                 if (temp_sprite.time > 60)
  1260.                         if ( (scrollY > scrollY_min) && (scrollY > temp_sprite.posY - 0xA000) )
  1261.                                 scrollY -= 0x400;
  1262.                
  1263.         } else if (input_new.dir == 4 && input_old.dir == 4) {
  1264.                 temp_sprite.frame = 20;
  1265.                 if (temp_sprite.time > 60)
  1266.                         if (scrollY < scrollY_max && scrollY < (temp_sprite.posY))
  1267.                                 scrollY += 0x400;
  1268.         } else {
  1269.                 temp_sprite.think = TH_keen_ground;
  1270.         }
  1271.        
  1272.         if (input_new.but3 && !input_old.but3) {
  1273.                 temp_sprite.think = TH_keen_shoot_air;
  1274.                 temp_sprite.velX = temp_sprite.time = temp_sprite.varC = 0;
  1275.         }
  1276.        
  1277.         if (temp_sprite.varD !=0)
  1278.                 temp_sprite.varD = 0;
  1279.        
  1280.         /*
  1281.         CM_do_fall();
  1282.         CM_compute_sprite_delta();
  1283.         if (CM_check_ceiling() & EDGE_D)
  1284.                 CM_kill_keen_temp();
  1285.        
  1286.         */
  1287.         return;
  1288. }
  1289.  
  1290.        
  1291. void ADD_stunner(long x, long y, short dir) {
  1292.        
  1293.         Sprite* s;
  1294.         short vx, vy;
  1295.         vx = vy = 0;
  1296.                
  1297.         s = CM_add_sprite();
  1298.         s->type = 10;
  1299.         s->posX = x;
  1300.         s->posY = y;
  1301.         s->think = TH_stunner_flight;
  1302.         s->contact = CO_stunner;
  1303.         s->frame = 0x6c;
  1304.         s->varD = 0; // spawning flag; set after first call to think
  1305.        
  1306.         switch (dir) {
  1307.        
  1308.                 case 0:
  1309.                         vy = -400;
  1310.                         break;
  1311.                 case 1:
  1312.                         vy = -284;
  1313.                         vx = 284;
  1314.                         break;
  1315.                 case 2:
  1316.                         vx = 400;
  1317.                         break;
  1318.                 case 3:
  1319.                         vx = 284;
  1320.                         vy = 284;
  1321.                         break;
  1322.                 case 4:
  1323.                         vy = 400;
  1324.                         break;
  1325.                 case 5:
  1326.                         vx = -284;
  1327.                         vy = 284;
  1328.                         break;
  1329.                 case 6:
  1330.                         vx = -400;
  1331.                         break;
  1332.                 case 7:
  1333.                         vx = -284;
  1334.                         vy = -284;
  1335.                         break;
  1336.                 default:
  1337.                         break;
  1338.         }
  1339.        
  1340.         s->velX = vx;
  1341.         s->velY = vy;
  1342.        
  1343.         return;
  1344. }
  1345.  
  1346. void TH_stunner_flight(void) {
  1347.        
  1348.         // check if spawned inside only on first think call, then csd
  1349.         if ( (!temp_sprite.varD && CM_spawned_inside()) || CM_compute_sprite_delta()) {
  1350.                 set_cur_sound(37);
  1351.                 temp_sprite.type = 13;
  1352.                 temp_sprite.think = TH_stunner_zapzot;
  1353.                 temp_sprite.time = 0;
  1354.                
  1355.                 if (get_random() > 0x80)
  1356.                         temp_sprite.frame = 0x6e;
  1357.                 else
  1358.                         temp_sprite.frame = 0x6f;
  1359.        
  1360.         }
  1361.         temp_sprite.varD = 1;
  1362.         return;
  1363. }
  1364.  
  1365.  
  1366. void TH_stunner_zapzot(void) {
  1367.         temp_sprite.type = 0;
  1368.         return;
  1369. }
  1370.  
  1371. void CO_stunner(Sprite *stunner, Sprite *sp) {
  1372.        
  1373.         if (sp->type != 1 && sp->type != 14) {
  1374.                
  1375.                 set_cur_sound(37);
  1376.                 stunner->think = TH_stunner_zapzot;
  1377.                 stunner->contact = CO_nop;
  1378.                 stunner->velX = stunner->velY = 0;
  1379.        
  1380.                 if (get_random() > 0x80)
  1381.                         stunner->frame = 0x6e;
  1382.                 else
  1383.                         stunner->frame = 0x6f;
  1384.         }
  1385.  
  1386.         return;
  1387. }
  1388.  
  1389.  
  1390. void TH_keen_exit(void) {
  1391.        
  1392.         long t1, t2;
  1393.         t1 = (long)temp_sprite.varA; //tilex
  1394.         t2 = (long)temp_sprite.varB; //tiley
  1395.        
  1396.         temp_sprite.delX = sprite_sync * 60;
  1397.         temp_sprite.frame = 0 + ((ticks>>4) & 3);
  1398.         keen_facing = temp_sprite.velX;
  1399.        
  1400.         // cover all four exit tiles
  1401.         slide_sprite(tile2map(t1),   tile2map(t2),   160);
  1402.         slide_sprite(tile2map(t1),   tile2map((t2+1)), 160);
  1403.         slide_sprite(tile2map((t1+1)), tile2map(t2),   143);
  1404.         slide_sprite(tile2map((t1+1)), tile2map((t2+1)), 143);
  1405.        
  1406.         t1 = tile2map((t1+1));
  1407.         if (t1 <= temp_sprite.posX) {
  1408.                 temp_sprite.type = 0;
  1409.                 level_finished = LEVEL_EXIT;
  1410.         }
  1411.        
  1412.         return;
  1413. }
  1414.  
  1415. void TH_keen_dead(void) {
  1416.        
  1417.         temp_sprite.time += sprite_sync;
  1418.         if (temp_sprite.time > 200) {
  1419.                 temp_sprite.time = -999;
  1420.                 temp_sprite.velX = get_random() - 0x80;
  1421.                 temp_sprite.velY = -400;
  1422.         }
  1423.        
  1424.         temp_sprite.frame = ((ticks >> 4) & 1) + 22;
  1425.         temp_sprite.delX = temp_sprite.velX * sprite_sync;
  1426.         temp_sprite.delY = temp_sprite.velY * sprite_sync;
  1427.        
  1428.         if (temp_sprite.boxY2 < scrollY)
  1429.                 temp_sprite.type = 0;
  1430.         return;        
  1431.        
  1432. }
  1433.  
  1434. void CM_kill_keen(void) {
  1435.         sprites[0].think = TH_keen_dead;
  1436.         sprites[0].contact = CO_nop;
  1437.         sprites[0].posY += 0x800;
  1438.         sprites[0].time = sprites[0].velY = sprites[0].velX = 0;
  1439.         sprites[0].frame = 22;
  1440.         set_cur_sound(8);
  1441.         return;
  1442. }
  1443.  
  1444. void CM_kill_keen_temp(void) {
  1445.        
  1446.         temp_sprite.think = TH_keen_dead;
  1447.         temp_sprite.contact = CO_nop;
  1448.         temp_sprite.posY += 0x800;
  1449.         temp_sprite.time = temp_sprite.velY = temp_sprite.velX = 0;
  1450.         temp_sprite.frame = 22;
  1451.         set_cur_sound(8);
  1452.         return;
  1453. }
  1454.  
  1455. void CO_keen(Sprite *s1, Sprite *s2) {
  1456.         return;
  1457. }
  1458.  
  1459.  
  1460. // called from first think-call after spawning a sprite
  1461. // returns nonzero if sprite was spawned inside block
  1462. short CM_spawned_inside(void) {
  1463.        
  1464.         short tx, ty, tx1, tx2, ty1, ty2, bl;
  1465.        
  1466.         tx1 = map2tile(temp_sprite.boxX1);
  1467.         tx2 = map2tile(temp_sprite.boxX2);
  1468.         ty1 = map2tile(temp_sprite.boxY1);
  1469.         ty2 = map2tile(temp_sprite.boxY2);
  1470.         bl = 0;
  1471.        
  1472.         // check x if velx != 0
  1473.         if (temp_sprite.velX > 0) {
  1474.                 for (tx = tx2 - 1, ty = ty1; ty <= ty2; ty++)
  1475.                         if (TI_LEdge[map_data_tiles[ty * map_width_T + tx]])
  1476.                                 bl | EDGE_L;
  1477.                        
  1478.         } else if (temp_sprite.velX < 0) {
  1479.                 for (tx = tx1 + 1, ty = ty1; ty <= ty2; ty++)
  1480.                         if (TI_REdge[map_data_tiles[ty * map_width_T + tx]])
  1481.                                 bl | EDGE_R;
  1482.         }
  1483.        
  1484.         // check y if vely != 0
  1485.         if (temp_sprite.velY > 0) {
  1486.                 for (ty = ty2 - 1, tx = tx1; tx <= tx2; tx++)
  1487.                         if (TI_UEdge[map_data_tiles[ty * map_width_T + tx]])
  1488.                                 bl | EDGE_U;
  1489.                        
  1490.         } else if (temp_sprite.velY < 0) {
  1491.                 for (ty = ty1 + 1, tx = tx1; tx <= tx2; tx++)
  1492.                         if (TI_DEdge[map_data_tiles[ty * map_width_T + tx]])
  1493.                                 bl | EDGE_D;
  1494.         }
  1495.        
  1496.         return bl;
  1497.        
  1498.  
  1499. }      
  1500.        
  1501. void TH_nop(void) {
  1502.         return;
  1503. }
  1504.  
  1505. void CO_nop(Sprite *s1, Sprite *s2) {
  1506.         return;
  1507. }
  1508.  
  1509. void BO_nop(Body *bp) {
  1510.         return;
  1511. }
  1512.  
  1513.  
  1514.  
  1515.  
  1516. /*
  1517. void janitor_walk(void) {
  1518.  
  1519.         int bl;
  1520.        
  1521.         // varA stores temp velX
  1522.         // if varC, sprite is walking, else it is pausing
  1523.         if (temp_sprite.varC) {
  1524.                 // 2 frame loop; base frame is 100 for right, 102 for left, speed 5
  1525.                 if (temp_sprite.velX > 0)
  1526.                         temp_sprite.frame = 100;
  1527.                 else
  1528.                         temp_sprite.frame = 102;
  1529.                 temp_sprite.frame += ((ticks >> 5) & 1);
  1530.        
  1531.         } else {
  1532.                 // look at screen for random amount of time
  1533.                 temp_sprite.frame = 104;
  1534.                 if (get_random() > 0xE0) {
  1535.                         temp_sprite.velX = temp_sprite.varA;
  1536.                         temp_sprite.varC = 1;
  1537.                 }
  1538.         }
  1539.                
  1540.         do_fall();
  1541.         bl = compute_sprite_delta();
  1542.                        
  1543.         //bird falls off edge
  1544.         if (!(bl & EDGE_U)) {
  1545.                 temp_sprite.delX = -(temp_sprite.delX << 1); // set bird back on edge
  1546.                 temp_sprite.delY = 0;                                             // no vertical displacement
  1547.                 temp_sprite.velX = -temp_sprite.velX;             // reverse velocity
  1548.                 temp_sprite.frame = 104;
  1549.                 return;        
  1550.         }
  1551.        
  1552.         // hits a wall, turns around
  1553.         if (bl & EDGE_L) {     
  1554.                 temp_sprite.varA = -90;
  1555.                 temp_sprite.frame = 104;
  1556.                 temp_sprite.velX = temp_sprite.varC = 0;
  1557.                 return;
  1558.         }
  1559.        
  1560.         if (bl & EDGE_R) {
  1561.                 temp_sprite.varA = 90;
  1562.                 temp_sprite.frame = 100;
  1563.                 temp_sprite.velX = temp_sprite.varC = 0;
  1564.                 return;
  1565.         }
  1566.        
  1567.         return;
  1568.  
  1569. }
  1570.  
  1571. void janitor_start(void) {
  1572.  
  1573.         do_fall();
  1574.         if (compute_sprite_delta() & 2)
  1575.                 temp_sprite.think = loc_func(janitor_walk);
  1576.                
  1577. }
  1578.  
  1579.  
  1580. // no operation
  1581. void janitor_contact(Sprite *janitor, Sprite *other) {
  1582.        
  1583.         if (other->type == 10 || other->type == 11) {
  1584.                 janitor->time = 0;
  1585.                 janitor->frame = 105;
  1586.                 janitor->think = loc_func(sprite_kill);
  1587.                 janitor->contact = loc_func(contact_none);
  1588.                 janitor->velY = -80;
  1589.                 set_cur_sound(34);
  1590.         }
  1591.        
  1592.         return;
  1593. }
  1594.  
  1595. //
  1596. void add_janitor(short tx, short ty) {
  1597.  
  1598.         Sprite *b;
  1599.        
  1600.         b = add_sprite();
  1601.         b->type = 2;
  1602.         b->posX = tile2map(tx);
  1603.         b->posY = tile2map(ty);
  1604.         b->velX = 90;
  1605.         b->varC = 1;
  1606.        
  1607.         if (b->posX > sprites[0].posX)
  1608.                 b->velX = -(b->velX);
  1609.                
  1610.         b->think = loc_func(janitor_start);
  1611.         b->contact = loc_func(janitor_contact);
  1612.         b->frame = 100;
  1613.         return;        
  1614.  
  1615. }
  1616.  
  1617. // one frame sprite death
  1618. void sprite_kill(void) {
  1619.        
  1620.         temp_sprite.type = 14;
  1621.         if ((temp_sprite.time += sprite_sync) > 40) {
  1622.                
  1623.                 temp_sprite.time = 0;
  1624.                 temp_sprite.frame++;
  1625.                 temp_sprite.think = loc_func(sprite_dead);
  1626.         }
  1627.        
  1628.         temp_sprite.velX = 0;
  1629.         do_fall();
  1630.         compute_sprite_delta();
  1631.        
  1632. }
  1633.  
  1634.  
  1635.  
  1636. void sprite_dead(void) {
  1637.        
  1638.         temp_sprite.time++;
  1639.         do_fall();
  1640.         compute_sprite_delta();
  1641.        
  1642. }
  1643.  
  1644. */