home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / macabuse / src / ant.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-20  |  14.6 KB  |  630 lines

  1. #include "ant.hpp"
  2. #include "lisp.hpp"
  3. #include "lisp_gc.hpp"
  4. #include "compiled.hpp"
  5. #include "objects.hpp"
  6. #include "level.hpp"
  7. #include "game.hpp"
  8. #include "jrand.hpp"
  9. #include "clisp.hpp"
  10. #include "dev.hpp"
  11. #include "key_cfg.hpp"
  12. #include "status.hpp"
  13. #include <ctype.h>
  14.  
  15.  
  16. enum {  ANT_need_to_dodge,     // ant vars
  17.     ANT_no_see_time,
  18.     ANT_hide_flag };
  19.  
  20. void *ant_ai();
  21.  
  22. int can_see(game_object *o, long x1, long y1, long x2, long y2)
  23. {
  24.   long nx2=x2,ny2=y2;
  25.   current_level->vforeground_intersect(x1,y1,y2);
  26.   if (y2!=ny2) return 0;
  27.  
  28.   current_level->boundary_setback(o,x1,y1,x2,y2);
  29.   return (x2==nx2 && y2==ny2);
  30. }
  31.  
  32.  
  33. // if we first saw the player or it's been a while since we've seen the player then do a scream
  34. static void scream_check(game_object *o, game_object *b)
  35. {
  36.   if (can_see(o,o->x,o->y,b->x,b->y))
  37.   {
  38.     if (o->lvars[ANT_no_see_time]==0 || o->lvars[ANT_no_see_time]>20)
  39.       the_game->play_sound(S_ASCREAM_SND,127,o->x,o->y);      
  40.     o->lvars[ANT_no_see_time]=1;
  41.   } else o->lvars[ANT_no_see_time]++;
  42. }
  43.  
  44. int ant_congestion(game_object *o)
  45. {
  46.   for (game_object *d=current_level->first_active_object();d;d=d->next_active)
  47.   {
  48.     if (d->otype==o->otype && abs(o->x-d->x)<30 && abs(o->x-d->y)<20) return 1;
  49.   }
  50.   return 0;
  51. }
  52.  
  53. int ant_dodge(game_object *o)
  54. {
  55.   if (o->lvars[ANT_need_to_dodge]==1)
  56.   {
  57.     o->lvars[ANT_need_to_dodge]=0;
  58.     if ((jrand()%2)==0)
  59.     {
  60.       o->set_state(stopped);
  61.       o->set_aistate(ANT_JUMP);
  62.       if (!can_see(o,o->x,o->y,o->x,o->y-120))   // is there a roof above?
  63.       {
  64.     o->set_yvel(-17);
  65.     o->set_xvel(0);
  66.     o->set_aistate(ANT_JUMP_ROOF);
  67.     ant_ai();
  68.       } else
  69.       {
  70.     o->set_yvel(-12);
  71.     if (o->direction>0)
  72.       o->set_xvel(22);
  73.     else o->set_xvel(-22);
  74.     o->set_aistate(ANT_JUMP);
  75.       }
  76.     }
  77.     return 1;
  78.   } else return 0;
  79. }
  80.  
  81. static int alien_wait_time()
  82. {
  83.   void *v=symbol_value(l_difficulty);
  84.   if (v==l_easy)
  85.     return 6;
  86.   else if (v==l_medium)
  87.    return 4;
  88.   else if (v==l_hard)
  89.     return 2;
  90.   else return 1;
  91. }
  92.  
  93. static int can_hit_player(game_object *o, game_object *b)
  94. {  
  95.   return can_see(o,o->x+(o->direction>0?15:-15),o->y-15,b->x,b->y-15);
  96. }
  97.  
  98. static void fire_at_player(game_object *o, game_object *b)
  99. {
  100.   long firex=o->x+(o->direction>0?15:-15),firey=o->y-15,
  101.        playerx=b->x+b->xvel()*8,playery=b->y-15+b->yvel()*2;
  102.   if (can_see(o,o->x,o->y,firex,firey) && can_see(o,firex,firey,playerx,playery))
  103.   {
  104.     int angle=lisp_atan2(firey-playery,playerx-firex);
  105.     void *call_list=NULL;
  106.     p_ref r1(call_list);
  107.     push_onto_list(new_lisp_pointer(b),call_list);
  108.     push_onto_list(new_lisp_number(angle),call_list);
  109.     push_onto_list(new_lisp_number(firey),call_list);
  110.     push_onto_list(new_lisp_number(firex),call_list);
  111.     push_onto_list(new_lisp_number(o->aitype()),call_list);
  112.     push_onto_list(new_lisp_pointer(o),call_list);
  113.     eval_user_fun((lisp_symbol *)l_fire_object,call_list);
  114.     o->set_state((character_state)S_weapon_fire);
  115.   }
  116. }
  117.  
  118. void *ant_ai()
  119. {
  120.   game_object *o=current_object,*b;
  121.  
  122.   if (o->hp()==0)    // if we are dead return NULL and get deleted
  123.   {
  124.     if (o->state==dead)
  125.     {
  126.       current_level->attacker(current_object)->controller()->kills++;
  127.       return NULL;
  128.     }
  129.     else o->set_state(dead);
  130.     return true_symbol;
  131.   }
  132.  
  133.  
  134.   if (o->state==flinch_up || o->state==flinch_down)
  135.   {
  136.     o->next_picture();
  137.     return true_symbol;
  138.   }
  139.  
  140.  
  141.   switch (o->aistate())
  142.   {
  143.     case ANT_START :
  144.     {
  145.       o->set_state((character_state)S_hanging);
  146.       if (o->lvars[ANT_hide_flag])
  147.         o->set_aistate(ANT_HIDING);
  148.  
  149.       else o->set_aistate(ANT_HANGING);
  150.     } break;
  151.     case ANT_HIDING :
  152.     {
  153.       if ((jrand()%128)==0) the_game->play_sound(S_SCARE_SND,127,o->x,o->y);
  154.       if (o->otype!=S_HIDDEN_ANT)
  155.       {
  156.     o->change_type(S_HIDDEN_ANT);      // switch types so noone hurts us.
  157.     o->set_state(stopped);
  158.     o->set_aistate(ANT_HIDING);
  159.       }
  160.  
  161.       int fall=0;
  162.       if (o->total_objects()==0)
  163.       {
  164.     if (player_list->next)
  165.       b=current_level->attacker(current_object);
  166.     else b=player_list->focus;
  167.     if (abs(b->x-o->x)<130 && (o->y<b->y))
  168.       fall=1;
  169.       }      
  170.       else if (o->get_object(0)->aistate()!=0)
  171.         fall=1;
  172.       
  173.       if (fall)
  174.       {
  175.     o->change_type(S_ANT_ROOF);
  176.     o->set_state((character_state)S_falling);
  177.     o->set_aistate(ANT_FALL_DOWN);
  178.     o->set_targetable(1);
  179.       } else o->set_targetable(0);
  180.     } break;
  181.     case ANT_HANGING :
  182.     {
  183.       int fall=0;
  184.       if ((jrand()%128)==0) the_game->play_sound(S_SCARE_SND,127,o->x,o->y);
  185.       if (o->lvars[ANT_hide_flag])
  186.         o->set_aistate(ANT_HIDING);
  187.       else
  188.       {
  189.     o->set_state((character_state)S_hanging);
  190.     if (o->total_objects())
  191.     {
  192.       if (o->get_object(0)->aistate()!=0)
  193.       fall=1;
  194.     } else
  195.     {
  196.       if (player_list->next)
  197.         b=current_level->attacker(current_object);
  198.       else b=player_list->focus;
  199.       if (abs(b->x-o->x)<130 && (o->y<b->y))
  200.       fall=1;
  201.     }
  202.     if (fall)
  203.     {
  204.       o->set_state((character_state)S_fall_start);
  205.       o->set_aistate(ANT_FALL_DOWN);
  206.       o->set_targetable(1);
  207.     } else o->set_targetable(0);
  208.       }
  209.       
  210.     } break;
  211.     case ANT_FALL_DOWN :
  212.     {
  213.       o->set_state((character_state)S_falling);
  214.        
  215.       if (player_list->next)
  216.       b=current_level->attacker(current_object);
  217.       else b=player_list->focus;
  218.       
  219.       scream_check(o,b);
  220.       int ret=o->mover(0,0,0);
  221.       if ((ret&BLOCKED_DOWN) || !can_see(o,o->x,o->y,o->x,o->y+1))
  222.       {
  223.     o->set_state((character_state)S_landing);
  224.     the_game->play_sound(S_ALAND_SND,127,o->x,o->y);
  225.     o->set_aistate(ANT_LANDING);
  226.       }
  227.     } break;
  228.     case ANT_LANDING :
  229.     {
  230.       if (!o->next_picture())
  231.       {
  232.     long xv=0,yv=2;
  233.     o->try_move(o->x,o->y,xv,yv,1);
  234.     if (yv!=0)
  235.     {
  236.       o->set_gravity(1);
  237.       o->set_aistate(ANT_FALL_DOWN);
  238.     }
  239.     else
  240.     { 
  241.       o->set_state(stopped);
  242.       o->set_aistate(ANT_RUNNING);
  243.       return ant_ai;
  244.     }
  245.       }
  246.     } break;
  247.     case ANT_RUNNING :
  248.     {
  249.       if (player_list->next)
  250.       b=current_level->attacker(current_object);
  251.       else b=player_list->focus;
  252.       scream_check(o,b);
  253.       
  254.       
  255.       if ((jrand()%16)==0)  
  256.       o->lvars[ANT_need_to_dodge]=1;
  257.       if (!ant_dodge(o))
  258.       {
  259.     if ((o->x>b->x && o->direction==-1) || (o->x<b->x && o->direction==1))
  260.     {
  261.       o->next_picture();
  262.       if ((jrand()%4)==0 && abs(o->x-b->x)<180 && abs(o->y-b->y)<100 && can_hit_player(o,b))
  263.       {
  264.         o->set_state((character_state)S_weapon_fire);
  265.         o->set_aistate(ANT_FIRE);
  266.       } else if (abs(o->x-b->x)<100 && abs(o->y-b->y)<10 && (jrand()%4)==0)
  267.         o->set_aistate(ANT_POUNCE_WAIT);
  268.       else if (abs(o->x-b->x)>140 && !ant_congestion(o))
  269.         o->set_aistate(ANT_JUMP);
  270.       else 
  271.       {
  272.         long xm=o->direction>0 ? get_ability(o->otype,run_top_speed) : -get_ability(o->otype,run_top_speed);
  273.         long ym=0,new_xm=xm;
  274.         if (o->state!=running) o->set_state(running);
  275.  
  276.         o->try_move(o->x,o->y,new_xm,ym,3);
  277.         if (new_xm!=xm)    // blocked, see if we can climb ramp
  278.         {
  279.           new_xm=xm;
  280.           ym=-abs(xm);
  281.           o->try_move(o->x,o->y,new_xm,ym,3);
  282.           if (new_xm==xm)
  283.           {
  284.         o->x+=new_xm;
  285.         o->y+=ym;
  286.         new_xm=0;
  287.         ym=abs(xm);      // now get back on the ground
  288.         o->try_move(o->x,o->y,new_xm,ym,3);
  289.         o->x+=new_xm;
  290.         o->y+=ym;
  291.           } else
  292.           {
  293.         o->direction=0-o->direction;
  294.         o->set_aistate(ANT_JUMP);
  295.           }
  296.         } else
  297.           o->x+=new_xm;
  298.         new_xm=0;
  299.         ym=10;       // see if we should fall
  300.         o->try_move(o->x,o->y,new_xm,ym,3);
  301.         if (ym==10)
  302.           o->set_aistate(ANT_FALL_DOWN);
  303.         else o->y+=ym;
  304.       }
  305.     } else
  306.     {
  307.       o->direction=o->x>b->x ? -1 : 1;
  308.       o->set_aistate(ANT_LANDING);
  309.     }
  310.       }
  311.     } break;
  312.     
  313.     case ANT_POUNCE_WAIT :
  314.     {
  315.       if (!ant_dodge(o))
  316.       {
  317.     o->set_state((character_state)S_pounce_wait);
  318.     if (o->aistate_time()>alien_wait_time())
  319.     {
  320.       the_game->play_sound(S_ASLASH_SND,127,o->x,o->y);
  321.       o->set_state(stopped);
  322.       o->set_aistate(ANT_JUMP);
  323.     }
  324.       }
  325.     } break;
  326.  
  327.     case ANT_JUMP :
  328.     {
  329.       o->lvars[ANT_need_to_dodge]=0;
  330.       if (o->move(o->direction,-1,0)&BLOCKED_DOWN)
  331.       o->set_aistate(ANT_RUNNING);     
  332.     } break;
  333.     case ANT_FIRE :
  334.     {
  335.       if (!ant_dodge(o))
  336.       {
  337.     if (o->state==S_fire_wait)
  338.     {
  339.       if (!o->next_picture() || symbol_value(l_difficulty)==l_extreme)
  340.       {
  341.         if (player_list->next)
  342.         b=current_level->attacker(current_object);
  343.         else b=player_list->focus;
  344.         fire_at_player(o,b);
  345.         o->set_state(stopped);
  346.         o->set_aistate(ANT_RUNNING);
  347.       }
  348.     } else o->set_state((character_state)S_fire_wait);
  349.       }
  350.     } break;
  351.     case ANT_JUMP_ROOF :
  352.     {
  353.       o->lvars[ANT_need_to_dodge]=0;
  354.       o->set_state((character_state)S_jump_up);
  355. //      o->set_yvel(o->yvel()+1);
  356.       o->set_xacel(0);
  357.       long xv=0,yv=o->yvel();
  358.       o->y-=31;
  359.       o->try_move(o->x,o->y,xv,yv,1);
  360.       o->y+=31+yv;
  361.       if (yv!=o->yvel())
  362.       {
  363.     if (o->yvel()>0)
  364.     {
  365.       o->set_state(stopped);
  366.       o->set_aistate(ANT_RUNNING);
  367.     } else
  368.     {
  369.       o->set_state((character_state)S_top_walk);
  370.       o->set_aistate(ANT_ROOF_WALK);
  371.     }
  372.     o->set_yvel(0);
  373.       }
  374.     } break;
  375.     case ANT_ROOF_WALK :
  376.     {
  377.       if (player_list->next)
  378.       b=current_level->attacker(current_object);
  379.       else b=player_list->focus;
  380.       scream_check(o,b);     
  381.       if (((jrand()%8)==0 && abs(o->x-b->x)<10 && o->y<b->y) ||
  382.       o->lvars[ANT_need_to_dodge]==1)
  383.       {
  384.     o->set_gravity(1);
  385.     o->set_state(run_jump);
  386.     o->set_aistate(ANT_JUMP);
  387.     ant_ai();
  388.       }
  389.       else
  390.       {
  391.     if ((o->x>b->x && o->direction>0) || (o->x<b->x && o->direction<0))
  392.     o->direction=-o->direction;
  393.     else if (abs(o->x-b->x)<120 && (jrand()%4)==0)
  394.     {
  395.       o->set_state((character_state)S_ceil_fire);
  396.       o->set_aistate(ANT_CEIL_SHOOT);
  397.       ant_ai();
  398.     } else
  399.     {
  400.       int speed=o->direction>0 ? get_ability(o->otype,run_top_speed) : 
  401.                 -get_ability(o->otype,run_top_speed);
  402.       if (can_see(o,o->x,o->y-31,o->x+speed,o->y-31) &&
  403.           !can_see(o,o->x+speed,o->y-31,o->x+speed,o->y-32))
  404.       {
  405.         o->x+=speed;
  406.         if (!o->next_picture()) o->set_state((character_state)S_top_walk);
  407.         
  408.       } else o->set_aistate(ANT_FALL_DOWN);
  409.     }
  410.       }
  411.     } break;
  412.     case ANT_CEIL_SHOOT :
  413.     {
  414.       if (!o->next_picture())
  415.       {
  416.     if (player_list->next)
  417.       b=current_level->attacker(current_object);
  418.     else b=player_list->focus;
  419.     fire_at_player(o,b);
  420.     o->set_state((character_state)S_top_walk);
  421.     o->set_aistate(ANT_ROOF_WALK);
  422.       }
  423.     } break;
  424.   }
  425.   
  426.  
  427.   
  428.   return true_symbol;
  429. }
  430.  
  431.  
  432.  
  433. void fade_in(image *im, int steps);
  434. void fade_out(int steps);
  435.  
  436. time_marker stat_show_start;
  437. static status_manager *old_stat;
  438.  
  439. class next_level_status_manager : public status_manager
  440. {
  441.   int level;
  442.   int x1,y1,x2,y2,color,last;
  443.   public :
  444.   next_level_status_manager(int x1, int y1, int x2, int y2, int color) : x1(x1),y1(y1),x2(x2),y2(y2),color(color)
  445.   {
  446.     level=0;
  447.     last=-1;
  448.   }
  449.  
  450.   virtual void push(char *name, visual_object *show)
  451.   {
  452.     level++;
  453.   }
  454.  
  455.   virtual void update(int percentage)
  456.   {
  457.     if (percentage!=last)
  458.     {
  459.       last=percentage;
  460.  
  461.       if (level==1)
  462.       {
  463.         int w=x1+(x2-x1)*percentage/100;
  464.         screen->bar(x1,y1,w,y2,color);
  465.         if (w<x2)
  466.           screen->bar(w,y1,x2,y2,0);
  467.       }
  468.       eh->flush_screen();
  469.     }
  470.  
  471.   }
  472.  
  473.   virtual void pop() { level--; }
  474.   virtual void force_display() { ; }
  475. } ;
  476.  
  477. void show_stats()
  478. {
  479.   if (current_level)
  480.   {
  481.     int xp,yp;
  482.  
  483.     if (!player_list->next)
  484.     {
  485.       fade_out(8);
  486.       eh->set_mouse_position(0,0);
  487.       screen->clear();
  488.  
  489.       switch_mode(VMODE_640x480);
  490.  
  491.       load_image_into_screen("art/frame.spe","end_level_screen",xp,yp);
  492.       fade_in(NULL,16);
  493.     } else
  494.     {
  495.       xp=screen->width()/2-640/2;
  496.       yp=screen->height()/2-480/2;
  497.     }
  498.  
  499.  
  500.  
  501.     char name[50];
  502.     strcpy(name,current_level->original_name());
  503.     char dig1=name[strlen(name)-strlen(".spe")-2];
  504.     char dig2=name[strlen(name)-strlen(".spe")-1];
  505.  
  506.    
  507.     char msg[50];
  508.     int lev_num;
  509.  
  510.  
  511.     if (isdigit(dig1) && isdigit(dig2))
  512.       lev_num=(dig1-'0')*10+dig2-'0';
  513.     else
  514.       lev_num=dig2-'0';
  515.  
  516.     sprintf(msg,symbol_str("lev_complete"),lev_num);   
  517.  
  518.     int w=eh->font()->width()*strlen(msg),h=eh->font()->height();    
  519.     int x1=0,y1=0,x2=xres,y2=yres;
  520.     //    int x=(x1+x2)/2-w/2,y=(y1+y2)/2-h/2;
  521.     int x=444+xp,y=293+yp;   
  522.    
  523.     eh->font()->put_string(screen,x+1,y+1,msg,eh->dark_color());    
  524.     eh->font()->put_string(screen,x,y,msg,eh->bright_color());
  525.     
  526.     y+=eh->font()->height();
  527.     sprintf(msg,"Time taken.. %0.1f minutes",current_level->time_taken()/60.0);
  528.     eh->font()->put_string(screen,x+1,y+1,msg,eh->dark_color());    
  529.     eh->font()->put_string(screen,x,y,msg,eh->bright_color());
  530.  
  531.     y+=eh->font()->height();
  532.     sprintf(msg,"Kills....... %d",player_list->kills);
  533.     eh->font()->put_string(screen,x+1,y+1,msg,eh->dark_color());    
  534.     eh->font()->put_string(screen,x,y,msg,eh->bright_color());
  535.  
  536.  
  537.  
  538.     eh->flush_screen();
  539.     stat_show_start.get_time();
  540.  
  541.     old_stat=stat_man;
  542.     stat_man=new next_level_status_manager(xp+443,yp+424,xp+589,yp+443,93);  
  543.   }
  544. }
  545.  
  546.  
  547.  
  548. void end_stats()
  549. {
  550.   time_marker now;
  551.   while (now.diff_time(&stat_show_start)<2)
  552.     now.get_time();
  553.  
  554.   view *f=player_list;
  555.   for (;f;f=f->next)
  556.     f->kills=0;
  557.  
  558.   fade_out(8);
  559.   switch_mode(VMODE_320x200);
  560.   pal->load();
  561.   stat_man=old_stat;
  562. }
  563.  
  564.  
  565.  
  566. void scatter_line(int x1, int y1, int x2, int y2, int c, int s)
  567. {
  568.   short cx1,cy1,cx2,cy2;
  569.   screen->get_clip(cx1,cy1,cx2,cy2);
  570.  
  571.   int t=abs(x2-x1)>abs(y2-y1) ? abs(x2-x1)+1 : abs(y2-y1)+1;
  572.   long xo=x1<<16,yo=y1<<16,dx=((x2-x1)<<16)/t,dy=((y2-y1)<<16)/t,count=0,x,y;
  573.   uchar *sl;
  574.  
  575.   int xm=(1<<s);
  576.   int ym=(1<<s);
  577.   s=(15-s);
  578.  
  579.  
  580.   while (t--)
  581.   {
  582.     x=(xo>>16)+(jrand()>>s)-xm;
  583.     y=(yo>>16)+(jrand()>>s)-ym;
  584.     if (!(x<cx1 || y<cy1 || x>cx2 || y>cy2))
  585.       *(screen->scan_line(y)+x)=c;
  586.     xo+=dx; yo+=dy;
  587.   }
  588.  
  589. }
  590.  
  591.  
  592.  
  593. void ascatter_line(int x1, int y1, int x2, int y2, int c1, int c2, int s)
  594. {
  595.   short cx1,cy1,cx2,cy2;
  596.   screen->get_clip(cx1,cy1,cx2,cy2);
  597.  
  598.  
  599.   int t=abs(x2-x1)>abs(y2-y1) ? abs(x2-x1)+1 : abs(y2-y1)+1;
  600.   long xo=x1<<16,yo=y1<<16,dx=((x2-x1)<<16)/t,dy=((y2-y1)<<16)/t,count=0,x,y;
  601.   uchar *sl;
  602.  
  603.   int xm=(1<<s);
  604.   int ym=(1<<s);
  605.   s=(15-s);
  606.  
  607.   int w=screen->width();
  608.   uchar *addr;
  609.  
  610.  
  611.   while (t--)
  612.   {
  613.     x=(xo>>16)+(jrand()>>s)-xm;
  614.     y=(yo>>16)+(jrand()>>s)-ym;
  615.     if (!(x<=cx1 || y<=cy1 || x>=cx2 || y>=cy2))
  616.     {
  617.       addr=screen->scan_line(y)+x;
  618.       *addr=c1;
  619.       *(addr+w)=c2;
  620.       *(addr-w)=c2;
  621.       *(addr-1)=c2;
  622.       *(addr+1)=c2;
  623.     }
  624.     xo+=dx; yo+=dy;
  625.   }
  626.  
  627. }
  628.  
  629.  
  630.