ZoriaRPG

guys.cpp 12-June-2017

Jun 12th, 2017
120
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //--------------------------------------------------------
  2. //--------------------------------------------------------
  3. //  Zelda Classic
  4. //  by Jeremy Craner, 1999-2000
  5. //
  6. //  guys.cc
  7. //
  8. //  "Guys" code (and other related stuff) for zelda.cc
  9. //
  10. //--------------------------------------------------------
  11.  
  12. #include "precompiled.h" //always first
  13.  
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include "zc_alleg.h"
  17. #include "guys.h"
  18. #include "zelda.h"
  19. #include "zsys.h"
  20. #include "maps.h"
  21. #include "link.h"
  22. #include "subscr.h"
  23. #include "ffscript.h"
  24. #include "defdata.h"
  25. #include "mem_debug.h"
  26. #include "zscriptversion.h"
  27. #include "backend/AllBackends.h"
  28.  
  29. extern LinkClass   Link;
  30. extern sprite_list  guys, items, Ewpns, Lwpns, Sitems, chainlinks, decorations;
  31. extern zinitdata    zinit;
  32.  
  33. int repaircharge=0;
  34. bool adjustmagic=false;
  35. bool learnslash=false;
  36. int wallm_load_clk=0;
  37. int sle_x,sle_y,sle_cnt,sle_clk;
  38. int vhead=0;
  39. int guycarryingitem=0;
  40.  
  41. char *guy_string[eMAXGUYS];
  42.  
  43. void never_return(int index);
  44. void playLevelMusic();
  45.  
  46. // If an enemy is this far out of the playing field, just remove it.
  47. #define OUTOFBOUNDS ((int)y>((tmpscr->flags7&fSIDEVIEW && canfall(id))?192:352) || y<-176 || x<-256 || x > 512)
  48.  
  49. namespace
  50. {
  51.     int trapConstantHorizontalID;
  52.     int trapConstantVerticalID;
  53.     int trapLOSHorizontalID;
  54.     int trapLOSVerticalID;
  55.     int trapLOS4WayID;
  56.    
  57.     int cornerTrapID;
  58.     int centerTrapID;
  59.    
  60.     int rockID;
  61.     int zoraID;
  62.     int statueID;
  63. }
  64.  
  65. void identifyCFEnemies()
  66. {
  67.     trapConstantHorizontalID=-1;
  68.     trapConstantVerticalID=-1;
  69.     trapLOSHorizontalID=-1;
  70.     trapLOSVerticalID=-1;
  71.     trapLOS4WayID=-1;
  72.     cornerTrapID=-1;
  73.     centerTrapID=-1;
  74.     rockID=-1;
  75.     zoraID=-1;
  76.     statueID=-1;
  77.    
  78.     for(int i=0; i<eMAXGUYS; i++)
  79.     {
  80.         if((guysbuf[i].flags2&cmbflag_trph) && trapLOSHorizontalID==-1)
  81.             trapLOSHorizontalID=i;
  82.         if((guysbuf[i].flags2&cmbflag_trpv) && trapLOSVerticalID==-1)
  83.             trapLOSVerticalID=i;
  84.         if((guysbuf[i].flags2&cmbflag_trp4) && trapLOS4WayID==-1)
  85.             trapLOS4WayID=i;
  86.         if((guysbuf[i].flags2&cmbflag_trplr) && trapConstantHorizontalID==-1)
  87.             trapConstantHorizontalID=i;
  88.         if((guysbuf[i].flags2&cmbflag_trpud) && trapConstantVerticalID==-1)
  89.             trapConstantVerticalID=i;
  90.        
  91.         if((guysbuf[i].flags2&eneflag_trap) && cornerTrapID==-1)
  92.             cornerTrapID=i;
  93.         if((guysbuf[i].flags2&eneflag_trp2) && centerTrapID==-1)
  94.             centerTrapID=i;
  95.        
  96.         if((guysbuf[i].flags2&eneflag_rock) && rockID==-1)
  97.             rockID=i;
  98.         if((guysbuf[i].flags2&eneflag_zora) && zoraID==-1)
  99.             zoraID=i;
  100.        
  101.         if((guysbuf[i].flags2 & eneflag_fire) && statueID==-1)
  102.             statueID=i;
  103.     }
  104. }
  105.  
  106. int random_layer_enemy()
  107. {
  108.     int cnt=count_layer_enemies();
  109.    
  110.     if(cnt==0)
  111.     {
  112.         return eNONE;
  113.     }
  114.    
  115.     int ret=rand()%cnt;
  116.     cnt=0;
  117.    
  118.     for(int i=0; i<6; ++i)
  119.     {
  120.         if(tmpscr->layermap[i]!=0)
  121.         {
  122.             mapscr *layerscreen=&TheMaps[(tmpscr->layermap[i]-1)*MAPSCRS]+tmpscr->layerscreen[i];
  123.            
  124.             for(int j=0; j<10; ++j)
  125.             {
  126.                 if(layerscreen->enemy[j]!=0)
  127.                 {
  128.                     if(cnt==ret)
  129.                     {
  130.                         return layerscreen->enemy[j];
  131.                     }
  132.                    
  133.                     ++cnt;
  134.                 }
  135.             }
  136.         }
  137.     }
  138.    
  139.     return eNONE;
  140. }
  141.  
  142. int count_layer_enemies()
  143. {
  144.     int cnt=0;
  145.    
  146.     for(int i=0; i<6; ++i)
  147.     {
  148.         if(tmpscr->layermap[i]!=0)
  149.         {
  150.             mapscr *layerscreen=&TheMaps[(tmpscr->layermap[i]-1)*MAPSCRS]+tmpscr->layerscreen[i];
  151.            
  152.             for(int j=0; j<10; ++j)
  153.             {
  154.                 if(layerscreen->enemy[j]!=0)
  155.                 {
  156.                     ++cnt;
  157.                 }
  158.             }
  159.         }
  160.     }
  161.    
  162.     return cnt;
  163. }
  164.  
  165. int link_on_wall()
  166. {
  167.     int lx = Link.getX();
  168.     int ly = Link.getY();
  169.    
  170.     if(lx>=48 && lx<=192)
  171.     {
  172.         if(ly==32)  return up+1;
  173.        
  174.         if(ly==128) return down+1;
  175.     }
  176.    
  177.     if(ly>=48 && ly<=112)
  178.     {
  179.         if(lx==32)  return left+1;
  180.        
  181.         if(lx==208) return right+1;
  182.     }
  183.    
  184.     return 0;
  185. }
  186.  
  187. bool tooclose(int x,int y,int d)
  188. {
  189.     return (abs(int(LinkX())-x)<d && abs(int(LinkY())-y)<d);
  190. }
  191.  
  192. // Returns true iff a combo type or flag precludes enemy movement.
  193. bool groundblocked(int dx, int dy)
  194. {
  195.     return COMBOTYPE(dx,dy)==cPIT || COMBOTYPE(dx,dy)==cPITB || COMBOTYPE(dx,dy)==cPITC ||
  196.            COMBOTYPE(dx,dy)==cPITD || COMBOTYPE(dx,dy)==cPITR ||
  197.            // Block enemies type and block enemies flags
  198.            combo_class_buf[COMBOTYPE(dx,dy)].block_enemies&1 ||
  199.            MAPFLAG(dx,dy)==mfNOENEMY || MAPCOMBOFLAG(dx,dy)==mfNOENEMY ||
  200.            MAPFLAG(dx,dy)==mfNOGROUNDENEMY || MAPCOMBOFLAG(dx,dy)==mfNOGROUNDENEMY ||
  201.            // Check for ladder-only combos which aren't dried water
  202.            (combo_class_buf[COMBOTYPE(dx,dy)].ladder_pass&1 && !iswater_type(COMBOTYPE(dx,dy))) ||
  203.            // Check for drownable water
  204.            (get_bit(quest_rules,qr_DROWN) && !(tmpscr->flags7&fSIDEVIEW) && (iswater(MAPCOMBO(dx,dy))));
  205. }
  206.  
  207. // Returns true iff enemy is floating and blocked by a combo type or flag.
  208. bool flyerblocked(int dx, int dy, int special)
  209. {
  210.     return ((special==spw_floater)&&
  211.             ((COMBOTYPE(dx,dy)==cNOFLYZONE)||
  212.              (combo_class_buf[COMBOTYPE(dx,dy)].block_enemies&4)||
  213.              (MAPFLAG(dx,dy)==mfNOENEMY)||
  214.              (MAPCOMBOFLAG(dx,dy)==mfNOENEMY)));
  215. }
  216.  
  217. bool m_walkflag(int dx,int dy,int special, int x=-1000, int y=-1000)
  218. {
  219.     int yg = (special==spw_floater)?8:0;
  220.     int nb = get_bit(quest_rules, qr_NOBORDER) ? 16 : 0;
  221.    
  222.     if(dx<16-nb || dy<zc_max(16-yg-nb,0) || dx>=240+nb || dy>=160+nb)
  223.         return true;
  224.        
  225.     if(isdungeon() || special==spw_wizzrobe)
  226.     {
  227.         if((x>=32 && dy<32-yg) || (y>-1000 && y<=144 && dy>=144))
  228.             return true;
  229.            
  230.         if((x>=32 && dx<32) || (x>-1000 && x<224 && dx>=224))
  231.             if(special!=spw_door)                                 // walk in door way
  232.                 return true;
  233.     }
  234.    
  235.     switch(special)
  236.     {
  237.     case spw_clipbottomright:
  238.         if(dy>=128 || dx>=208) return true;
  239.        
  240.     case spw_clipright:
  241.         break; //if(x>=208) return true; break;
  242.        
  243.     case spw_wizzrobe:
  244.     case spw_floater:
  245.         return false;
  246.     }
  247.    
  248.     dx&=(special==spw_halfstep)?(~7):(~15);
  249.     dy&=(special==spw_halfstep || tmpscr->flags7&fSIDEVIEW)?(~7):(~15);
  250.    
  251.     if(special==spw_water)
  252.         return (water_walkflag(dx,dy+8,1) || water_walkflag(dx+8,dy+8,1));
  253.        
  254.     return _walkflag(dx,dy+8,1) || _walkflag(dx+8,dy+8,1) ||
  255.            groundblocked(dx,dy+8) || groundblocked(dx+8,dy+8);
  256. }
  257.  
  258.  
  259. /**********************************/
  260. /*******  Enemy Base Class  *******/
  261. /**********************************/
  262.  
  263. /* ROM data flags
  264.  
  265.   */
  266.  
  267. enemy::enemy(fix X,fix Y,int Id,int Clk) : sprite()
  268. {
  269.     x=X;
  270.     y=Y;
  271.     id=Id;
  272.     clk=Clk;
  273.     floor_y=y;
  274.     ceiling=false;
  275.     fading = misc = clk2 = clk3 = stunclk = hclk = sclk = superman = 0;
  276.     grumble = movestatus = posframe = timer = ox = oy = 0;
  277.     yofs = playing_field_offset - ((tmpscr->flags7&fSIDEVIEW) ? 0 : 2);
  278.     did_armos=true;
  279.     script_spawned=false;
  280.    
  281.     d = guysbuf + (id & 0xFFF);
  282.     hp = d->hp;
  283.     starting_hp = hp;
  284. //  cs = d->cset;
  285. //d variables
  286.  
  287.     flags=d->flags;
  288.     flags2=d->flags2;
  289.     s_tile=d->s_tile; //secondary (additional) tile(s)
  290.     family=d->family;
  291.     dcset=d->cset;
  292.     cs=dcset;
  293.     anim=get_bit(quest_rules,qr_NEWENEMYTILES)?d->e_anim:d->anim;
  294.     dp=d->dp;
  295.     wdp=d->wdp;
  296.     wpn=d->weapon;
  297.     wpnsprite = d-> wpnsprite; //2.6 -Z
  298.     rate=d->rate;
  299.     hrate=d->hrate;
  300.     dstep=d->step;
  301.     homing=d->homing;
  302.     dmisc1=d->misc1;
  303.     dmisc2=d->misc2;
  304.     dmisc3=d->misc3;
  305.     dmisc4=d->misc4;
  306.     dmisc5=d->misc5;
  307.     dmisc6=d->misc6;
  308.     dmisc7=d->misc7;
  309.     dmisc8=d->misc8;
  310.     dmisc9=d->misc9;
  311.     dmisc10=d->misc10;
  312.     dmisc11=d->misc11;
  313.     dmisc12=d->misc12;
  314.     dmisc13=d->misc13;
  315.     dmisc14=d->misc14;
  316.     dmisc15=d->misc15;
  317.    
  318.     for(int i=0; i<edefLAST; i++)
  319.         defense[i]=d->defense[i];
  320.    
  321.     bgsfx=d->bgsfx;
  322.     hitsfx=d->hitsfx;
  323.     deadsfx=d->deadsfx;
  324.     bosspal=d->bosspal;
  325.    
  326.     if(bosspal>-1)
  327.     {
  328.         loadpalset(csBOSS,pSprite(bosspal));
  329.     }
  330.    
  331.     if(bgsfx>-1)
  332.     {
  333.         Backend::sfx->loop(bgsfx,128);
  334.     }
  335.    
  336.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  337.     {
  338.         o_tile=d->e_tile;
  339.         frate = d->e_frate;
  340.     }
  341.     else
  342.     {
  343.         o_tile=d->tile;
  344.         frate = d->frate;
  345.     }
  346.    
  347.     tile=0;
  348.    
  349.     // If they forgot the invisibility flag, here's another failsafe:
  350.     if(o_tile==0 && family!=eeSPINTILE)
  351.         flags |= guy_invisible;
  352.        
  353. //  step = d->step/100.0;
  354.     // To preserve the odd step values for Keese & Gleeok heads. -L
  355.     if(dstep==62.0) dstep+=0.5;
  356.     else if(dstep==89) dstep-=1/9;
  357.    
  358.     step = dstep/100.0;
  359.    
  360.    
  361.     item_set = d->item_set;
  362.     grumble = d->grumble;
  363.    
  364.     if(frate == 0)
  365.         frate = 256;
  366.        
  367.     leader = itemguy = dying = scored = false;
  368.     canfreeze = count_enemy = true;
  369.     mainguy = !(flags & guy_doesntcount);
  370.     dir = rand()&3;
  371.    
  372.     //2.6 Enemy Editor Hit and TIle Sizes
  373.     if ( d->txsz > 0 ) { txsz = d->txsz; if ( txsz > 1 ) extend = 3; } //! Don;t forget to set extend if the tilesize is > 1.
  374.     //al_trace("->txsz:%i\n", d->txsz); Verified that this is setting the value. -Z
  375.    // al_trace("Enemy txsz:%i\n", txsz);
  376.     if ( d->tysz > 0 ) { tysz = d->tysz; if ( tysz > 1 ) extend = 3; }
  377.     if ( d->hxsz > 0 ) hxsz = d->hxsz;
  378.     if ( d->hysz > 0 ) hysz = d->hysz;
  379.     if ( d->hzsz > 0 ) hzsz = d->hzsz;
  380.     if ( d->hxofs != 0 ) hxofs = d->hxofs;
  381.     if ( d->hyofs != 0 ) hyofs = d->hyofs;
  382.    
  383.     if ( d->xofs != 0 ) xofs = (int)d->xofs;
  384.     if ( d->yofs != 0 ) yofs = (int)d->yofs;
  385.     if ( d->zofs != 0 ) zofs = (int)d->zofs;
  386.    
  387.     if((wpn==ewBomb || wpn==ewSBomb) && family!=eeOTHER && family!=eeFIRE && (family!=eeWALK || dmisc2 != e2tBOMBCHU))
  388.         wpn = 0;
  389. }
  390.  
  391. enemy::~enemy() {}
  392.  
  393. // Supplemental animation code that all derived classes should call
  394. // as a return value for animate().
  395. // Handles the death animation and returns true when enemy is finished.
  396. bool enemy::Dead(int index)
  397. {
  398.     if(dying)
  399.     {
  400.         --clk2;
  401.        
  402.         if(clk2==12 && hp>-1000)                                // not killed by ringleader
  403.             death_sfx();
  404.            
  405.         if(clk2==0)
  406.         {
  407.             if(flags&guy_neverret)
  408.                 never_return(index);
  409.                
  410.             if(leader)
  411.                 kill_em_all();
  412.                
  413.             leave_item();
  414.         }
  415.        
  416.         stop_bgsfx(index);
  417.         return (clk2==0);
  418.     }
  419.    
  420.     return false;
  421. }
  422.  
  423. // Basic animation code that all derived classes should call.
  424. // The one with an index is the one that is called by
  425. // the guys sprite list; index is the enemy's index in the list.
  426. bool enemy::animate(int index)
  427. {
  428.     int nx = real_x(x);
  429.     int ny = real_y(y);
  430.    
  431.     if(ox!=nx || oy!=ny)
  432.     {
  433.         posframe=(posframe+1)%(get_bit(quest_rules,qr_NEWENEMYTILES)?4:2);
  434.     }
  435.    
  436.     ox = nx;
  437.     oy = ny;
  438.    
  439.     // Maybe they fell off the bottom in sideview, or were moved by a script.
  440.     if(OUTOFBOUNDS)
  441.         hp=-1000;
  442.        
  443.     //fall down
  444.     if(canfall(id) && fading != fade_flicker && clk>=0)
  445.     {
  446.         if(tmpscr->flags7&fSIDEVIEW)
  447.         {
  448.             if(!ON_SIDEPLATFORM)
  449.             {
  450.                 y+=fall/100;
  451.                
  452.                 if(fall <= (int)zinit.terminalv)
  453.                     fall += zinit.gravity;
  454.             }
  455.             else
  456.             {
  457.                 if(fall!=0)   // Only fix pos once
  458.                     y-=(int)y%8; // Fix position
  459.                    
  460.                 fall = 0;
  461.             }
  462.         }
  463.         else
  464.         {
  465.             if(fall!=0)
  466.                 z-=(fall/100);
  467.                
  468.             if(z<0)
  469.                 z = fall = 0;
  470.             else if(fall <= (int)zinit.terminalv)
  471.                 fall += zinit.gravity;
  472.         }
  473.     }
  474.    
  475.     // clk is incremented here
  476.     if(++clk >= frate)
  477.         clk=0;
  478.        
  479.     // hit and death handling
  480.     if(hclk>0)
  481.         --hclk;
  482.        
  483.     if(stunclk>0)
  484.         --stunclk;
  485.        
  486.     if(ceiling && z<=0)
  487.         ceiling = false;
  488.        
  489.     if(!dying && hp<=0)
  490.     {
  491.         if(itemguy && (hasitem&2)!=0)
  492.         {
  493.             for(int i=0; i<items.Count(); i++)
  494.             {
  495.                 if(((item*)items.spr(i))->pickup&ipENEMY)
  496.                 {
  497.                     items.spr(i)->x = x;
  498.                     items.spr(i)->y = y - 2;
  499.                 }
  500.             }
  501.         }
  502.        
  503.         dying=true;
  504.        
  505.         if(fading==fade_flash_die)
  506.             clk2=19+18*4;
  507.         else
  508.         {
  509.             clk2 = BSZ ? 15 : 19;
  510.            
  511.             if(fading!=fade_blue_poof)
  512.                 fading=0;
  513.         }
  514.        
  515.         if(itemguy)
  516.         {
  517.             hasitem&=~2;
  518.             item_set=0;
  519.         }
  520.        
  521.         if(currscr<128 && count_enemy && !script_spawned)
  522.             game->guys[(currmap<<7)+currscr]-=1;
  523.     }
  524.    
  525.     scored=false;
  526.    
  527.     ++c_clk;
  528.    
  529.     // returns true when enemy is defeated
  530.     return Dead(index);
  531. }
  532.  
  533. // Stops playing the given sound only if there are no enemies left to play it
  534. void enemy::stop_bgsfx(int index)
  535. {
  536.     if(bgsfx<=0)
  537.         return;
  538.        
  539.     Backend::sfx->unloop(bgsfx);
  540. }
  541.  
  542.  
  543. // to allow for different sfx on defeating enemy
  544. void enemy::death_sfx()
  545. {
  546.     if(deadsfx > 0)
  547.         Backend::sfx->play(deadsfx,x);
  548. }
  549.  
  550. void enemy::move(fix dx,fix dy)
  551. {
  552.     if(!watch && (!(tmpscr->flags7&fSIDEVIEW) || ON_SIDEPLATFORM || !canfall(id)))
  553.     {
  554.         x+=dx;
  555.         y+=dy;
  556.     }
  557. }
  558.  
  559. void enemy::move(fix s)
  560. {
  561.     if(!watch && (!(tmpscr->flags7&fSIDEVIEW) || ON_SIDEPLATFORM || !canfall(id)))
  562.         sprite::move(s);
  563. }
  564.  
  565. void enemy::leave_item()
  566. {
  567.     int drop_item = select_dropitem(item_set, x, y);
  568.    
  569.     if(drop_item!=-1&&((itemsbuf[drop_item].family!=itype_fairy)||!m_walkflag(x,y,0)))
  570.     {
  571.         if(extend >= 3) items.add(new item(x+(txsz-1)*8,y+(tysz-1)*8,(fix)0,drop_item,ipBIGRANGE+ipTIMER,0));
  572.         else items.add(new item(x,y,(fix)0,drop_item,ipBIGRANGE+ipTIMER,0));
  573.     }
  574. }
  575.  
  576. // auomatically kill off enemy (for rooms with ringleaders)
  577. void enemy::kickbucket()
  578. {
  579.     if(!superman)
  580.         hp=-1000;                                               // don't call death_sfx()
  581. }
  582.  
  583. void enemy::FireBreath(bool seeklink)
  584. {
  585.     if(wpn==wNone)
  586.         return;
  587.    
  588.     if(wpn==ewFireTrail)
  589.     {
  590.         dmisc1 = e1tEACHTILE;
  591.         FireWeapon();
  592.         return;
  593.     }
  594.    
  595.     float fire_angle=0.0;
  596.     int wx=0, wy=0, wdir=dir;
  597.    
  598.     if(!seeklink)
  599.     {
  600.         switch(dir)
  601.         {
  602.         case down:
  603.             fire_angle=PI*((rand()%20)+10)/40;
  604.             wx=x;
  605.             wy=y+8;
  606.             break;
  607.            
  608.         case -1:
  609.         case up:
  610.             fire_angle=PI*((rand()%20)+50)/40;
  611.             wx=x;
  612.             wy=y-8;
  613.             break;
  614.            
  615.         case left:
  616.             fire_angle=PI*((rand()%20)+30)/40;
  617.             wx=x-8;
  618.             wy=y;
  619.             break;
  620.            
  621.         case right:
  622.             fire_angle=PI*((rand()%20)+70)/40;
  623.             wx=x+8;
  624.             wy=y;
  625.             break;
  626.         }
  627.        
  628.         if(wpn==ewFlame || wpn==ewFlame2)
  629.         {
  630.             if(fire_angle==-PI || fire_angle==PI) wdir=left;
  631.             else if(fire_angle==-PI/2) wdir=up;
  632.             else if(fire_angle==PI/2) wdir=down;
  633.             else if(fire_angle==0) wdir=right;
  634.             else if(fire_angle<-PI/2) wdir=l_up;
  635.             else if(fire_angle<0) wdir=r_up;
  636.             else if(fire_angle<(PI/2)) wdir=r_down;
  637.             else if(fire_angle<PI) wdir=l_down;
  638.         }
  639.     }
  640.     else
  641.     {
  642.         wx = x;
  643.         wy = y;
  644.     }
  645.    
  646.     addEwpn(wx,wy,z,wpn,2,wdp,seeklink ? 0xFF : wdir, getUID());
  647.     Backend::sfx->play(wpnsfx(wpn),int(x));
  648.    
  649.     int i=Ewpns.Count()-1;
  650.     weapon *ew = (weapon*)(Ewpns.spr(i));
  651.    
  652.     if(!seeklink && (rand()&4))
  653.     {
  654.         ew->angular=true;
  655.         ew->angle=fire_angle;
  656.     }
  657.    
  658.     if(wpn==ewFlame && wpnsbuf[ewFLAME].frames>1)
  659.     {
  660.         ew->aframe=rand()%wpnsbuf[ewFLAME].frames;
  661.         ew->tile+=ew->aframe;
  662.     }
  663.    
  664.     for(int j=Ewpns.Count()-1; j>0; j--)
  665.     {
  666.         Ewpns.swap(j,j-1);
  667.     }
  668. }
  669.  
  670. void enemy::FireWeapon()
  671. {
  672.     /*
  673.      * Type:
  674.      * 0x01: Boss fireball
  675.      * 0x02: Seeks Link
  676.      * 0x04: Fast projectile
  677.      * 0x00-0x30: If 0x02, slants toward (type>>3)-1
  678.      */
  679.     if(wpn<wEnemyWeapons && dmisc1!=9 && dmisc1!=10)  // Summoning doesn't require weapons
  680.         return;
  681.        
  682.     if(wpn==ewFireTrail && dmisc1>=e1t3SHOTS && dmisc1<=e1t8SHOTS)
  683.         dmisc1 = e1tEACHTILE;
  684.        
  685.     switch(dmisc1)
  686.     {
  687.     case e1t5SHOTS: //BS-Aquamentus
  688.         Ewpns.add(new weapon(x,y,z,wpn,2+(((dir^left)+5)<<3),wdp,dir,-1, getUID(),false));
  689.         Ewpns.add(new weapon(x,y,z,wpn,2+(((dir^right)+5)<<3),wdp,dir,-1, getUID(),false));
  690.        
  691.         //fallthrough
  692.     case e1t3SHOTSFAST:
  693.     case e1t3SHOTS: //Aquamentus
  694.         Ewpns.add(new weapon(x,y,z,wpn,2+(((dir^left)+1)<<3)+(dmisc1==e1t3SHOTSFAST ? 4:0),wdp,dir,-1, getUID(),false));
  695.         Ewpns.add(new weapon(x,y,z,wpn,2+(((dir^right)+1)<<3)+(dmisc1==e1t3SHOTSFAST ? 4:0),wdp,dir,-1, getUID(),false));
  696.        
  697.         //fallthrough
  698.     default:
  699.         Ewpns.add(new weapon(x,y,z,wpn,2+(dmisc1==e1t3SHOTSFAST || dmisc1==e1tFAST ? 4:0),wdp,wpn==ewFireball2 || wpn==ewFireball ? 0:dir,-1, getUID(),false));
  700.         Backend::sfx->play(wpnsfx(wpn),int(x));
  701.         break;
  702.        
  703.     case e1tSLANT:
  704.     {
  705.         int slant = 0;
  706.        
  707.         if(((Link.x-x) < -8 && dir==up) || ((Link.x-x) > 8 && dir==down) || ((Link.y-y) < -8 && dir==left) || ((Link.y-y) > 8 && dir==right))
  708.             slant = left;
  709.         else if(((Link.x-x) > 8 && dir==up) || ((Link.x-x) < -8 && dir==down) || ((Link.y-y) > 8 && dir==left) || ((Link.y-y) < -8 && dir==right))
  710.             slant = right;
  711.            
  712.         Ewpns.add(new weapon(x,y,z,wpn,2+(((dir^slant)+1)<<3),wdp,wpn==ewFireball2 || wpn==ewFireball ? 0:dir,-1, getUID(),false));
  713.         Backend::sfx->play(wpnsfx(wpn),int(x));
  714.         break;
  715.     }
  716.    
  717.     case e1t8SHOTS: //Fire Wizzrobe
  718.         Ewpns.add(new weapon(x,y,z,wpn,0,wdp,l_up,-1, getUID(),false));
  719.         Ewpns.add(new weapon(x,y,z,wpn,0,wdp,l_down,-1, getUID(),false));
  720.         Ewpns.add(new weapon(x,y,z,wpn,0,wdp,r_up,-1, getUID(),false));
  721.         Ewpns.add(new weapon(x,y,z,wpn,0,wdp,r_down,-1, getUID(),false));
  722.        
  723.         //fallthrough
  724.     case e1t4SHOTS: //Stalfos 3
  725.         Ewpns.add(new weapon(x,y,z,wpn,0,wdp,up,-1, getUID(),false));
  726.         Ewpns.add(new weapon(x,y,z,wpn,0,wdp,down,-1, getUID(),false));
  727.         Ewpns.add(new weapon(x,y,z,wpn,0,wdp,left,-1, getUID(),false));
  728.         Ewpns.add(new weapon(x,y,z,wpn,0,wdp,right,-1, getUID(),false));
  729.         Backend::sfx->play(wpnsfx(wpn), int(x));
  730.         break;
  731.        
  732.     case e1tSUMMON: // Bat Wizzrobe
  733.     {
  734.         if(dmisc4==0) break;  // Summon 0
  735.        
  736.         int bc=0;
  737.        
  738.         for(int gc=0; gc<guys.Count(); gc++)
  739.         {
  740.             if((((enemy*)guys.spr(gc))->id) == dmisc3)
  741.             {
  742.                 ++bc;
  743.             }
  744.         }
  745.        
  746.         if(bc<=40)  // Not too many enemies
  747.         {
  748.             int kids = guys.Count();
  749.             int bats=(rand()%zc_max(1,dmisc4))+1;
  750.            
  751.             for(int i=0; i<bats; i++)
  752.             {
  753.                 if(addenemy(x,y,dmisc3,-10))
  754.                     ((enemy*)guys.spr(kids+i))->count_enemy = false;
  755.             }
  756.            
  757.             Backend::sfx->play(get_bit(quest_rules,qr_MORESOUNDS) ? WAV_ZN1SUMMON : WAV_FIRE,int(x));
  758.         }
  759.        
  760.         break;
  761.     }
  762.    
  763.     case e1tSUMMONLAYER: // Summoner
  764.     {
  765.         if(count_layer_enemies()==0)
  766.         {
  767.             break;
  768.         }
  769.        
  770.         int kids = guys.Count();
  771.        
  772.         if(kids<40)
  773.         {
  774.             int newguys=(rand()%3)+1;
  775.             bool summoned=false;
  776.            
  777.             for(int i=0; i<newguys; i++)
  778.             {
  779.                 int id2=vbound(random_layer_enemy(),eSTART,eMAXGUYS-1);
  780.                 int x2=0;
  781.                 int y2=0;
  782.                
  783.                 for(int k=0; k<20; ++k)
  784.                 {
  785.                     x2=16*((rand()%12)+2);
  786.                     y2=16*((rand()%7)+2);
  787.                    
  788.                     if((!m_walkflag(x2,y2,0))&&((abs(x2-Link.getX())>=32)||(abs(y2-Link.getY())>=32)))
  789.                     {
  790.                         if(addenemy(x2,y2,get_bit(quest_rules,qr_ENEMIESZAXIS) ? 64 : 0,id2,-10))
  791.                             ((enemy*)guys.spr(kids+i))->count_enemy = false;
  792.                            
  793.                         summoned=true;
  794.                         break;
  795.                     }
  796.                 }
  797.             }
  798.            
  799.             if(summoned)
  800.             {
  801.                 Backend::sfx->play(get_bit(quest_rules,qr_MORESOUNDS) ? WAV_ZN1SUMMON : WAV_FIRE,int(x));
  802.             }
  803.         }
  804.        
  805.         break;
  806.     }
  807.     }
  808. }
  809.  
  810. //! Weapon Editor for 2.6
  811. //To hell with this. I'm writing new functions to resolve weapon type and defence. -Z
  812.  
  813. int enemy::getWeaponID(weapon *w){
  814.     int wpnID;
  815.    
  816.     if ( w->parentitem == -1 ) {
  817.         al_trace("enemy::getWeaponID(*w), Step 1B, checking parentitem; parentitem == -1, eturning w->id: \n", w->id);
  818.         Z_message("enemy::getWeaponID(*w), Step 1B, checking parentitem; parentitem == -1, eturning w->id: \n", w->id);
  819.         return w->id;
  820.        
  821.     }
  822.     if ( w->parentitem > -1 ) {
  823.         al_trace("enemy::getWeaponID(*w), Step 1B, checking parentitem; parentitem > -1, and is: \n", w->parentitem);
  824.         Z_message("enemy::getWeaponID(*w), Step 1B, checking parentitem; parentitem > -1, and is: \n", w->parentitem);
  825.    
  826.         int usewpn = itemsbuf[w->parentitem].useweapon;
  827.         al_trace("enemy::getWeaponID(*w), Step 2, getting itemsbuf[w->parentitem].useweapon; usewpn is: \n", usewpn);
  828.         Z_message("enemy::getWeaponID(*w), Step 2, getting itemsbuf[w->parentitem].useweapon; usewpn is: \n", usewpn);
  829.    
  830.         if ( usewpn > 0 ) {
  831.            
  832.             wpnID = usewpn; //Not forwarding to the weapon sprite?
  833.             al_trace("enemy::getWeaponID(*w), Step 3A, useweapon > 0; setting wpnID = useweapon; wpnID is: \n", wpnID);
  834.             Z_message("enemy::getWeaponID(*w), Step 3A, useweapon > 0; setting wpnID = useweapon; wpnID is: \n", wpnID);
  835.         }
  836.         else {
  837.             wpnID = w->id;
  838.             al_trace("enemy::getWeaponID(*w), Step 3A, useweapon !> 0; setting wpnID = w->id; wpnID is: \n", wpnID);
  839.             Z_message("enemy::getWeaponID(*w), Step 3A, useweapon !> 0; setting wpnID = w->id; wpnID is: \n", wpnID);
  840.            
  841.         }
  842.         return wpnID;
  843.     }
  844.     else {
  845.         return w->id;
  846.     }
  847.  
  848. }
  849.  
  850. int enemy::resolveEnemyDefence(weapon *w){
  851.     int weapondef = -1; //To suppress compiler warnings.
  852.     al_trace("enemy::resolveEnemyDefence(), Step 0, initial weapondef should be -1, and is: \n", weapondef);
  853.     Z_message("enemy::resolveEnemyDefence(), Step 0, initial weapondef should be -1, and is: \n", weapondef);
  854.     int wid = getWeaponID(w);
  855.     al_trace("enemy::resolveEnemyDefence(), Step 1, initial wid: \n", wid);
  856.     Z_message("enemy::resolveEnemyDefence(), Step 1, initial wid: \n", wid);
  857.    
  858.     if ( w->parentitem > -1 ) {
  859.         int usedef = itemsbuf[w->parentitem].usedefence;
  860.        
  861.         al_trace("enemy::resolveEnemyDefence(), Step 2, reading itemsbuf[itm].usedefence: \n", usedef);
  862.         Z_message("enemy::resolveEnemyDefence(), Step 2, reading itemsbuf[itm].usedefence: \n", usedef);
  863.        
  864.         al_trace("enemy::resolveEnemyDefence(), Step 3, reading defense[wid]: \n", defense[wid]);
  865.         Z_message("enemy::resolveEnemyDefence(), Step 3, reading defense[wid]: \n", defense[wid]);
  866.        
  867.         if ( defense[wid] == 0 ) {
  868.             weapondef = usedef;
  869.             al_trace("enemy::resolveEnemyDefence(), Step 4A, defense[wid] == 0; edef = usedef; edef is: \n", weapondef);
  870.             Z_message("enemy::resolveEnemyDefence(), Step 4A, defense[wid] == 0; edef = usedef; edef is: \n", weapondef);
  871.         }
  872.         else weapondef = defense[wid]; //defense] is not in the same order as weapon id enum, is it?
  873.         al_trace("enemy::resolveEnemyDefence(), Step 4A, defense[wid] != 0; edef = defense[wid]; edef is: \n", weapondef);
  874.         Z_message("enemy::resolveEnemyDefence(), Step 4A, defense[wid] != 0; edef = defense[wid]; edef is: \n", weapondef);
  875.         return weapondef;
  876.     }
  877.     al_trace("enemy::resolveEnemyDefence(), Step 5, returning defense[wid]: \n", defense[wid]);
  878.     Z_message("enemy::resolveEnemyDefence(), Step 5, returning defense[wid]: \n", defense[wid]);
  879.     return defense[wid];
  880. }
  881.  
  882.  
  883.  
  884.  
  885. // Hit the shield(s)?
  886. // Apparently, this function is only used for hookshots...
  887. bool enemy::hitshield(int wpnx, int wpny, int xdir)
  888. {
  889.     if(!(family==eeWALK || family==eeFIRE || family==eeOTHER))
  890.         return false;
  891.        
  892.     bool ret = false;
  893.    
  894.     // TODO: There must be some bitwise operations that can simplify this...
  895.     if(wpny > y) ret = ((flags&inv_front && xdir==down) || (flags&inv_back && xdir==up) || (flags&inv_left && xdir==left) || (flags&inv_right && xdir==right));
  896.     else if(wpny < y) ret = ((flags&inv_front && xdir==up) || (flags&inv_back && xdir==down) || (flags&inv_left && xdir==right) || (flags&inv_right && xdir==left));
  897.    
  898.     if(wpnx < x) ret = ret || ((flags&inv_front && xdir==left) || (flags&inv_back && xdir==right) || (flags&inv_left && xdir==up) || (flags&inv_right && xdir==down));
  899.     else if(wpnx > x) ret = ret || ((flags&inv_front && xdir==right) || (flags&inv_back && xdir==left) || (flags&inv_left && xdir==down) || (flags&inv_right && xdir==up));
  900.    
  901.     return ret;
  902. }
  903.  
  904. // Check defenses without actually acting on them.
  905. bool enemy::candamage(int power, int edef)
  906. {
  907.     switch(defense[edef])
  908.     {
  909.     case edSTUNORCHINK:
  910.     case edSTUNORIGNORE:
  911.     case edSTUNONLY:
  912.     case edCHINK:
  913.     case edIGNORE:
  914.         return false;
  915.        
  916.     case edIGNOREL1:
  917.     case edCHINKL1:
  918.         return power >= 1*DAMAGE_MULTIPLIER;
  919.        
  920.     case edCHINKL2:
  921.         return power >= 2*DAMAGE_MULTIPLIER;
  922.        
  923.     case edCHINKL4:
  924.         return power >= 4*DAMAGE_MULTIPLIER;
  925.        
  926.     case edCHINKL6:
  927.         return power >= 6*DAMAGE_MULTIPLIER;
  928.        
  929.     case edCHINKL8:
  930.         return power >= 8*DAMAGE_MULTIPLIER;
  931.     }
  932.    
  933.     return true;
  934. }
  935.  
  936. // Do we do damage?
  937. // 0: takehit returns 0
  938. // 1: takehit returns 1
  939. // -1: do damage
  940. int enemy::defend(int wpnId, int *power, int edef)
  941. {
  942.         switch ( wpnId ){
  943.             case wBrang:
  944.             al_trace("enemy::defend(), wpnID input is: LW_BRANG: \n", wpnId);
  945.             Z_message("enemy::defend(), wpnID input is: BLW_BRANG: \n", wpnId);
  946.             break;
  947.            
  948.             case wHookshot:
  949.             al_trace("enemy::defend(), wpnID input is: LW_HOOKSHOT: \n", wpnId);
  950.             Z_message("enemy::defend(), wpnID input is: LW_HOOKSHOT: \n", wpnId);
  951.             break;
  952.            
  953.             // Anyway...
  954.             case wBomb:
  955.             al_trace("enemy::defend(), wpnID input is: LW_BOMB: \n", wpnId);
  956.             Z_message("enemy::defend(), wpnID input is: LW_BOMB: \n", wpnId);
  957.             break;
  958.            
  959.             case wSBomb:
  960.             al_trace("enemy::defend(), wpnID input is: LW_SBOMB: \n", wpnId);
  961.             Z_message("enemy::defend(), wpnID input is: LW_SBOMB: \n", wpnId);;
  962.             break;
  963.            
  964.             case wArrow:
  965.             al_trace("enemy::defend(), wpnID input is: LW_ARROW: \n", wpnId);
  966.             Z_message("enemy::defend(), wpnID input is: LW_ARROW: \n", wpnId);
  967.             break;
  968.            
  969.             case wFire:
  970.             al_trace("enemy::defend(), wpnID input is: LW_FIRE: \n", wpnId);
  971.             Z_message("enemy::defend(), wpnID input is: LW_FIRE: \n", wpnId);
  972.             break;
  973.            
  974.             case wWand:
  975.             al_trace("enemy::defend(), wpnID input is: LW_WAND: \n", wpnId);
  976.             Z_message("enemy::defend(), wpnID input is: LW_WAND: \n", wpnId);
  977.             break;
  978.            
  979.             case wMagic:
  980.             al_trace("enemy::defend(), wpnID input is: LW_MAGIC: \n", wpnId);
  981.             Z_message("enemy::defend(), wpnID input is: LW_MAGIC: \n", wpnId);
  982.             break;
  983.            
  984.             case wHammer:
  985.             al_trace("enemy::defend(), wpnID input is: LW_HAMMER: \n", wpnId);
  986.             Z_message("enemy::defend(), wpnID input is: LW_HAMMER: \n", wpnId);
  987.             break;
  988.            
  989.             case wSword:
  990.             al_trace("enemy::defend(), wpnID input is: LW_SWORD: \n", wpnId);
  991.             Z_message("enemy::defend(), wpnID input is: LW_SWORD: \n", wpnId);
  992.             break;
  993.            
  994.             case wBeam:
  995.             al_trace("enemy::defend(), wpnID input is: LW_BEAM: \n", wpnId);
  996.             Z_message("enemy::defend(), wpnID input is: LW_BEAM: \n", wpnId);
  997.             break;
  998.            
  999.             case wRefBeam:
  1000.             al_trace("enemy::defend(), wpnID input is: LW_REFBEAM: \n", wpnId);
  1001.             Z_message("enemy::defend(), wpnID input is: LW_REFBEAM: \n", wpnId);
  1002.             break;
  1003.            
  1004.             case wRefMagic:
  1005.             al_trace("enemy::defend(), wpnID input is: LW_REFMAGIC: \n", wpnId);
  1006.             Z_message("enemy::defend(), wpnID input is: LW_REFMAGIC: \n", wpnId);
  1007.             break;
  1008.            
  1009.             case wRefFireball:
  1010.             al_trace("enemy::defend(), wpnID input is: LW_REFFIREBALL: \n", wpnId);
  1011.             Z_message("enemy::defend(), wpnID input is: LW_REFFIREBALL: \n", wpnId);
  1012.             break;
  1013.            
  1014.             case wRefRock:
  1015.             al_trace("enemy::defend(), wpnID input is: LW_REFROCK: \n", wpnId);
  1016.             Z_message("enemy::defend(), wpnID input is: LW_REFROCK: \n", wpnId);
  1017.             break;
  1018.            
  1019.             case wStomp:
  1020.             al_trace("enemy::defend(), wpnID input is: LW_STOMP: \n", wpnId);
  1021.             Z_message("enemy::defend(), wpnID input is: LW_STOMP: \n", wpnId);
  1022.             break;
  1023.            
  1024.             case wCByrna:
  1025.             al_trace("enemy::defend(), wpnID input is: LW_BYRNA: \n", wpnId);
  1026.             Z_message("enemy::defend(), wpnID input is: L: \n", wpnId);
  1027.             break;
  1028.            
  1029.            
  1030.             case wScript1:
  1031.                 if(QHeader.zelda_version > 0x250) {
  1032.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT1: \n", wpnId);
  1033.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT1: \n", wpnId);
  1034.                 }
  1035.                 else {
  1036.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1037.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1038.                 }
  1039.             break;
  1040.            
  1041.             case wScript2:
  1042.                 if(QHeader.zelda_version > 0x250) {
  1043.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT2: \n", wpnId);
  1044.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT2: \n", wpnId);
  1045.                 }
  1046.                 else {
  1047.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1048.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1049.                 }
  1050.             break;
  1051.            
  1052.             case wScript3:
  1053.                 if(QHeader.zelda_version > 0x250) {
  1054.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT3: \n", wpnId);
  1055.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT3: \n", wpnId);
  1056.                 }
  1057.                 else {
  1058.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1059.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1060.                 }
  1061.             break;
  1062.            
  1063.             case wScript4:
  1064.                 if(QHeader.zelda_version > 0x250) {
  1065.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT4: \n", wpnId);
  1066.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT4: \n", wpnId);
  1067.                 }
  1068.                 else {
  1069.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1070.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1071.                 }
  1072.             break;
  1073.            
  1074.             case wScript5:
  1075.                 if(QHeader.zelda_version > 0x250) {
  1076.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT5: \n", wpnId);
  1077.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT5: \n", wpnId);
  1078.                 }
  1079.                 else {
  1080.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1081.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1082.                 }
  1083.             break;
  1084.            
  1085.             case wScript6:
  1086.                 if(QHeader.zelda_version > 0x250) {
  1087.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT6: \n", wpnId);
  1088.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT6: \n", wpnId);
  1089.                 }
  1090.                 else {
  1091.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1092.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1093.                 }
  1094.             break;
  1095.            
  1096.             case wScript7:
  1097.                 if(QHeader.zelda_version > 0x250) {
  1098.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT7: \n", wpnId);
  1099.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT7: \n", wpnId);
  1100.                 }
  1101.                 else {
  1102.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1103.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1104.                 }
  1105.             break;
  1106.            
  1107.             case wScript8:
  1108.                 if(QHeader.zelda_version > 0x250) {
  1109.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT8: \n", wpnId);
  1110.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT8: \n", wpnId);
  1111.                 }
  1112.                 else {
  1113.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1114.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1115.                 }
  1116.             break;
  1117.            
  1118.             case wScript9:
  1119.                 if(QHeader.zelda_version > 0x250) {
  1120.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT9: \n", wpnId);
  1121.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT9: \n", wpnId);
  1122.                 }
  1123.                 else {
  1124.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1125.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1126.                 }
  1127.             break;
  1128.            
  1129.             case wScript10:
  1130.                 if(QHeader.zelda_version > 0x250) {
  1131.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT10: \n", wpnId);
  1132.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version > 0x250; wpnID input is: LW_SCRIPT10: \n", wpnId);
  1133.                 }
  1134.                 else {
  1135.                     al_trace("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1136.                        Z_message("enemy::defend(), SCRIPT WEAPON, Quest Header Version !> 0x250; wpnID input is: LW_SCRIPT: \n", wpnId);
  1137.                 }
  1138.             break;
  1139.            
  1140.        
  1141.         }
  1142.     //Weapon Editor, Default Defence if set aqnd npc defence is none.
  1143.     //otherwise, use enemy editor definitions.  -Z
  1144.     int defence;
  1145.    
  1146.     al_trace("enemy::defend(), Step 1, checking defense[edef]: \n", defense[edef]);
  1147.     Z_message("enemy::defend(), Step 1, checking defense[edef]: \n", defense[edef]);
  1148.     if ( defense[edef] > 0 )
  1149.     {
  1150.         defence = defense[edef];
  1151.         al_trace("enemy::defend(), Step 2, defense[edef] > 0, setting defence: \n", defence);
  1152.         Z_message("enemy::defend(), Step 2, defense[edef] > 0, setting defence: \n", defence);
  1153.    
  1154.     }
  1155.     else
  1156.     {
  1157.         defence = edef; //itemsbuf[id].usedefense;
  1158.         al_trace("enemy::defend(), Step 3, defense[edef] !> 0, setting defence: \n", edef);
  1159.         Z_message("enemy::defend(), Step 2, defense[edef] !> 0, setting defence: \n", edef);
  1160.     }
  1161.     if(shieldCanBlock)
  1162.     {
  1163.         al_trace("enemy::defend(), shieldCanBlock, doing switch(defence) using a case of: \n", defence);
  1164.         Z_message("enemy::defend(), shieldCanBlock, doing switch(defence) using a case of: \n", defence);
  1165.         switch(defence)
  1166.         {
  1167.         case edIGNORE:
  1168.             return 0;
  1169.         case edIGNOREL1:
  1170.         case edSTUNORIGNORE:
  1171.             if(*power <= 0)
  1172.                 return 0;
  1173.         }
  1174.        
  1175.         Backend::sfx->play(WAV_CHINK,int(x));
  1176.         return 1;
  1177.     }
  1178.    
  1179.     al_trace("enemy::defend(), !shieldCanBlock, doing switch(defence) using a case of: \n", defence);
  1180.     Z_message("enemy::defend(), !shieldCanBlock, doing switch(defence) using a case of: \n", defence);
  1181.     switch(defence)
  1182.     {
  1183.     case edSTUNORCHINK:
  1184.         if(*power <= 0)
  1185.         {
  1186.             Backend::sfx->play(WAV_CHINK,int(x));
  1187.             return 1;
  1188.         }
  1189.        
  1190.     case edSTUNORIGNORE:
  1191.         if(*power <= 0)
  1192.             return 0;
  1193.            
  1194.     case edSTUNONLY:
  1195.         if((wpnId==wFire || wpnId==wBomb || wpnId==wSBomb || wpnId==wHookshot || wpnId==wSword) && stunclk>=159){
  1196.         al_trace("enemy::defend(), edSTUNONLY found a weapon of type FIRE, BOMB, SBOMB, HOOKSHOT, or SWORD:, with wpnId:  \n", wpnId);
  1197.         Z_message("enemy::defend(), edSTUNONLY found a weapon of type FIRE, BOMB, SBOMB, HOOKSHOT, or SWORD:, with wpnId:  \n", wpnId);
  1198.             return 1;
  1199.     }
  1200.         stunclk=160;
  1201.         Backend::sfx->play(WAV_EHIT,int(x));
  1202.         return 1;
  1203.        
  1204.     case edCHINKL1:
  1205.         if(*power >= 1*DAMAGE_MULTIPLIER) break;
  1206.        
  1207.     case edCHINKL2:
  1208.         if(*power >= 2*DAMAGE_MULTIPLIER) break;
  1209.        
  1210.     case edCHINKL4:
  1211.         if(*power >= 4*DAMAGE_MULTIPLIER) break;
  1212.        
  1213.     case edCHINKL6:
  1214.         if(*power >= 6*DAMAGE_MULTIPLIER) break;
  1215.        
  1216.     case edCHINKL8:
  1217.         if(*power >= 8*DAMAGE_MULTIPLIER) break;
  1218.    
  1219.     case edCHINKL10:
  1220.         if(*power >= 10*DAMAGE_MULTIPLIER) break;
  1221.        
  1222.     case edCHINK:
  1223.         Backend::sfx->play(WAV_CHINK,int(x));
  1224.         return 1;
  1225.        
  1226.     case edIGNOREL1:
  1227.         if(*power > 0)  break;
  1228.        
  1229.     case edIGNORE:
  1230.         return 0;
  1231.        
  1232.     case ed1HKO:
  1233.         *power = hp;
  1234.         return -2;
  1235.        
  1236.     case edTRIGGERSECRETS:
  1237.         hidden_entrance(0, true, false, -4);
  1238.     break;
  1239.        
  1240.     case ed2x:
  1241.     {
  1242.         *power = zc_max(1,*power*2);
  1243.     //int pow = *power;
  1244.         //*power = vbound((pow*2),0,214747);
  1245.     return -1;
  1246.     }
  1247.     case ed3x:
  1248.     {
  1249.         *power = zc_max(1,*power*3);
  1250.     //int pow = *power;
  1251.         //*power = vbound((pow*3),0,214747);
  1252.     return -1;
  1253.     }
  1254.    
  1255.     case ed4x:
  1256.     {
  1257.         *power = zc_max(1,*power*4);
  1258.     //int pow = *power;
  1259.         //*power = vbound((pow*4),0,214747);
  1260.     return -1;
  1261.     }
  1262.    
  1263.    
  1264.     case edHEAL:
  1265.     { //Probably needs its own function, or  routine in the damage functuon to heal if power is negative.
  1266.     //int pow = *power;
  1267.         //*power = vbound((pow*-1),0,214747);
  1268.     //break;
  1269.         *power = zc_min(0,*power*-1);
  1270.         return -1;
  1271.     }
  1272.     /*
  1273.     case edLEVELDAMAGE:
  1274.     {
  1275.     int pow = *power;
  1276.     int lvl  = *level;
  1277.         *power = vbound((pow*lvl),0,214747);
  1278.     break;
  1279.     }
  1280.     case edLEVELREDUCTION:
  1281.     {
  1282.     int pow = *power;
  1283.     int lvl  = *level;
  1284.         *power = vbound((pow/lvl),0,214747);
  1285.     break;
  1286.     }
  1287.     */
  1288.    
  1289.     case edQUARTDAMAGE:
  1290.         *power = zc_max(1,*power/2);
  1291.        
  1292.         //fallthrough
  1293.     case edHALFDAMAGE:
  1294.         *power = zc_max(1,*power/2);
  1295.         break;
  1296.     }
  1297.    
  1298.     return -1;
  1299. }
  1300.  
  1301.  
  1302.  
  1303. // Defend against a particular item class.
  1304. int enemy::defenditemclass(int wpnId, int *power, weapon *w)
  1305. //int useDefense, int weapon_override)
  1306. {
  1307.     int def=-1;
  1308.    
  1309.     //Weapon Editor -Z
  1310.     //if ( weapon_override > 0 ) wpnId = weapon_override; //Weapon editor override.
  1311.     //int wpn =
  1312.     //if ( useDefense > 0 ) {
  1313.         //THis would work if we want to override the defence, but we also only want to do it if
  1314.         //the enemy defence is 'NONE' for this weapon type, so we ead that in enemy::defend()
  1315.  
  1316.         //def = defend(getWeaponID(w), power, resolveEnemyDefence(w));
  1317.     //}
  1318.    
  1319.     int wid = getWeaponID(w);
  1320.    
  1321.    
  1322.         al_trace("enemy::defenditemclass(), Step 1, getting weapon ID; wid = getWeaponID. wid is: \n", wid);
  1323.         Z_message("enemy::defenditemclass(), Step 1, getting weapon ID; wid = getWeaponID. wid is: \n", wid);
  1324.                
  1325.     //else {
  1326.    
  1327.         switch(wid)
  1328.         {
  1329.         // These first 2 are only used by Gohma... enemy::takehit() has complicated stun-calculation code for these.
  1330.         case wBrang:
  1331.         case wBomb:
  1332.         case wHookshot:
  1333.         case wSBomb:
  1334.         case wArrow:
  1335.         case wFire:
  1336.         case wWand:
  1337.         case wMagic:
  1338.         case wHammer:
  1339.         case wSword:
  1340.         case wBeam:
  1341.         case wRefBeam:
  1342.         case wRefMagic:
  1343.         case wRefFireball:
  1344.         case wRefRock:
  1345.         case wStomp:
  1346.         case wCByrna:
  1347.         {
  1348.         def = defend(wid, power, resolveEnemyDefence(w));
  1349.             al_trace("enemy::defenditemclass(), Step 2A, wid is NOT a script type, doing defend(wid, power, resolveEnemyDefence(w); def is: \n", def);
  1350.             Z_message("enemy::defenditemclass(), Step 2A, wid is NOT a script type, doing defend(wid, power, resolveEnemyDefence(w); def is: \n", def);
  1351.         }
  1352.         break;
  1353.        
  1354.        
  1355.        
  1356.        
  1357.        
  1358.         case wScript1:
  1359.  
  1360.         case wScript2:
  1361.  
  1362.         case wScript3:
  1363.  
  1364.         case wScript4:
  1365.  
  1366.         case wScript5:
  1367.    
  1368.         case wScript6:
  1369.    
  1370.         case wScript7:
  1371.  
  1372.         case wScript8:
  1373.  
  1374.         case wScript9:
  1375.  
  1376.         case wScript10:
  1377.         {
  1378.             if(QHeader.zelda_version > 0x250)
  1379.             {
  1380.             def = defend(wid, power,  resolveEnemyDefence(w));
  1381.             al_trace("enemy::defenditemclass(), Step 2B, wid IS a SCRIPT TYPE and Quest Header Version > 0x250, doing defend(wid, power, resolveEnemyDefence(w); def is: \n", def);
  1382.             Z_message("enemy::defenditemclass(), Step 2B, wid IS a SCRIPT TYPE and Quest Header Version > 0x250, doing defend(wid, power, resolveEnemyDefence(w); def is: \n", def);
  1383.                
  1384.                
  1385.             }
  1386.             else
  1387.             {
  1388.             def = defend(wid, power,  edefSCRIPT);
  1389.             al_trace("enemy::defenditemclass(), Step 2B, wid IS a SCRIPT TYPE and Quest Header Version !> 0x250, doing defend(wid, power, edefSCRIPT; def is: \n", def);
  1390.             Z_message("enemy::defenditemclass(), Step 2B, wid IS a SCRIPT TYPE and Quest Header Version !> 0x250, doing defend(wid, power, edefSCRIPT(w); def is: \n", def);
  1391.             }
  1392.         }
  1393.         break;
  1394.        
  1395.        
  1396.         //!ZoriaRPG : We need some special cases here, to ensure that old script defs don;t break.
  1397.         //Probably best to do this from the qest file, loading the values of Script(generic) into each
  1398.         //of the ten if the quest version is lower than N.
  1399.         //Either that, or we need a boolean flag to set int he enemy editor, or by ZScript that changes this behaviour.
  1400.         //such as bool UseSeparatedScriptDefences. hah.
  1401.         default:
  1402.             def = defend(wid, power,  resolveEnemyDefence(w));
  1403.                 al_trace("enemy::defenditemclass(), reached DEFAULT, doing defend(wid, power, resolveEnemyDefence(w); def is: \n", def);
  1404.             Z_message("enemy::defenditemclass(), reached DEFAULT, doing defend(wid, power, resolveEnemyDefence(w); def is: \n", def);
  1405.                
  1406.         //if(wpnId>=wScript1 && wpnId<=wScript10)
  1407.         //{
  1408.          //   def = defend(wpnId, power, edefSCRIPT);
  1409.         //}
  1410.         //}
  1411.        
  1412.         break;
  1413.         }
  1414.        
  1415.         return def;
  1416.     //}
  1417. }
  1418.  
  1419. // take damage or ignore it
  1420. // -1: damage (if any) dealt
  1421. // 1: blocked
  1422. // 0: weapon passes through unhindered
  1423. // 2: heal enemy? -ZoriaRPG
  1424. int enemy::takehit(weapon *w)
  1425. {
  1426.    
  1427.     int wpnId;
  1428.     int trueID = w->id; //The true ID of the weapon, based on its type. -Z
  1429.     int power = w->power;
  1430.     int wpnx = w->x;
  1431.     int wpny = w->y;
  1432.     int wpnDir;
  1433.     int enemyHitWeapon = w->parentitem;
  1434.    
  1435.     //Weapon Editor.
  1436.     if ( enemyHitWeapon > -1 ) {
  1437.        
  1438.         if ( itemsbuf[enemyHitWeapon].useweapon > 0 ) { wpnId = itemsbuf[enemyHitWeapon].useweapon; }
  1439.         //The defined weapon type to use for enemy and combo interaction. -Z
  1440.         else wpnId = w->id; //if we are using s special weapon type, use the attributes from that weapon.
  1441.     }
  1442.    
  1443.    
  1444.     //Weapon Editor -Z
  1445.     byte def_overide = w->usedefence;
  1446.     byte wpn_override = w->useweapon;
  1447.    
  1448.     // If it's a boomerang that just bounced, use the opposite direction;
  1449.     // otherwise, it might bypass a shield. This probably won't handle
  1450.     // every case correctly, but it's better than having shields simply
  1451.     // not work against boomerangs.
  1452.     if(w->id==wBrang && w->misc==1 && w->clk2>=256 && w->clk2<264)
  1453.         wpnDir = oppositeDir[w->dir];
  1454.     else
  1455.         wpnDir = w->dir;
  1456.        
  1457.     if(dying || clk<0 || hclk>0 || superman)
  1458.     {
  1459.         return 0;
  1460.     }
  1461.    
  1462.     int ret = -1;
  1463.    
  1464.     // This obscure quest rule...
  1465.     if(get_bit(quest_rules,qr_BOMBDARKNUTFIX) && (wpnId==wBomb || wpnId==wSBomb))
  1466.     {
  1467.         double ddir=atan2(double(wpny-y),double(x-wpnx));
  1468.         wpnDir=rand()&3;
  1469.        
  1470.         if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4)))
  1471.         {
  1472.             wpnDir=down;
  1473.         }
  1474.         else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4)))
  1475.         {
  1476.             wpnDir=right;
  1477.         }
  1478.         else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/4)))
  1479.         {
  1480.             wpnDir=up;
  1481.         }
  1482.         else
  1483.         {
  1484.             wpnDir=left;
  1485.         }
  1486.     }
  1487.    
  1488.     int xdir = dir;
  1489.     shieldCanBlock=false;
  1490.    
  1491.     //if (family==eeFLOAT && flags&(inv_front|inv_back_inv_left|inv_right)) xdir=down;
  1492.     if((wpnId==wHookshot && hitshield(wpnx, wpny, xdir))
  1493.             || ((flags&inv_front && wpnDir==(xdir^down)) || (flags&inv_back && wpnDir==(xdir^up)) || (flags&inv_left && wpnDir==(xdir^left)) || (flags&inv_right && wpnDir==(xdir^right)))
  1494.       )
  1495.         // The hammer should already be dealt with by subclasses (Walker etc.)
  1496.     {
  1497.         switch(wpnId)
  1498.         {
  1499.             // Weapons which shields protect against
  1500.         case wSword:
  1501.         case wWand:
  1502.             if(Link.getCharging()>0)
  1503.                 Link.setAttackClk(Link.getAttackClk()+1); //Cancel charging
  1504.                
  1505.             //fallthrough
  1506.         case wHookshot:
  1507.         case wHSHandle:
  1508.         case wBrang:
  1509.             shieldCanBlock=true;
  1510.             break;
  1511.            
  1512.         case wBeam:
  1513.         case wRefBeam:
  1514.             // Mirror shielded enemies!
  1515. #if 0
  1516.             if(false /*flags2&guy_mirror*/ && !get_bit(quest_rules,qr_SWORDMIRROR))
  1517.             {
  1518.                 if(wpnId>wEnemyWeapons)
  1519.                     return 0;
  1520.                    
  1521.                 sfx(WAV_CHINK,pan(int(x)));
  1522.                 return 1;
  1523.             }
  1524.            
  1525. #endif
  1526.            
  1527.             //fallthrough
  1528.         case wRefRock:
  1529.         case wRefFireball:
  1530.         case wMagic:
  1531. #if 0
  1532.             if(false /*flags2&guy_mirror*/ && (wpnId!=wRefRock || get_bit(quest_rules,qr_REFLECTROCKS)))
  1533.             {
  1534.                 sfx(WAV_CHINK,pan(int(x)));
  1535.                 return 3;
  1536.             }
  1537.            
  1538. #endif
  1539.            
  1540.             if(wpnId>wEnemyWeapons)
  1541.                 return 0;
  1542.                
  1543.             //fallthrough
  1544.         default:
  1545.             shieldCanBlock=true;
  1546.             break;
  1547.            
  1548.             // Bombs
  1549.         case wSBomb:
  1550.         case wBomb:
  1551.             goto hitclock;
  1552.            
  1553.             // Weapons which ignore shields
  1554.         case wWhistle:
  1555.         case wHammer:
  1556.             break;
  1557.            
  1558.             // Weapons which shouldn't be removed by shields
  1559.         case wLitBomb:
  1560.         case wLitSBomb:
  1561.         case wWind:
  1562.         case wPhantom:
  1563.         case wSSparkle:
  1564.         case wBait:
  1565.             return 0;
  1566.            
  1567.         case wFire:
  1568. #if 0
  1569.             if(false /*flags2&guy_mirror*/)
  1570.             {
  1571.                 sfx(WAV_CHINK,pan(int(x)));
  1572.                 return 1;
  1573.             }
  1574.            
  1575. #endif
  1576.             ;
  1577.         }
  1578.     }
  1579.    
  1580.     switch(wpnId)
  1581.     {
  1582.     case wWhistle:
  1583.         return 0;
  1584.        
  1585.     case wPhantom:
  1586.         return 0;
  1587.        
  1588.     case wLitBomb:
  1589.     case wLitSBomb:
  1590.     case wBait:
  1591.     case wWind:
  1592.     case wSSparkle:
  1593.         return 0;
  1594.        
  1595.     case wFSparkle:
  1596.    
  1597.         // Only take sparkle damage if the sparkle's parent item is not
  1598.         // defended against.
  1599.         if(enemyHitWeapon > -1)
  1600.         {
  1601.             int p = 0;
  1602.             int f = itemsbuf[enemyHitWeapon].family;
  1603.            
  1604.             switch(f)
  1605.             {
  1606.             case itype_arrow:
  1607.                 if(!candamage(p, edefARROW)) return 0;
  1608.                
  1609.                 break;
  1610.                
  1611.             case itype_cbyrna:
  1612.                 if(!candamage(p, edefBYRNA)) return 0;
  1613.                
  1614.                 break;
  1615.                
  1616.             case itype_brang:
  1617.                 if(!candamage(p, edefBRANG)) return 0;
  1618.                
  1619.                 break;
  1620.                
  1621.             default:
  1622.                 return 0;
  1623.             }
  1624.         }
  1625.        
  1626.         wpnId = wSword;
  1627.         power = DAMAGE_MULTIPLIER>>1;
  1628.         goto fsparkle;
  1629.         break;
  1630.        
  1631.     case wBrang:
  1632.     {
  1633.         int def = defend(wpnId, &power, edefBRANG);
  1634.        
  1635.         if(def >= 0) return def;
  1636.        
  1637.         // Not hurt by 0-damage weapons
  1638.         if(!(flags & guy_bhit))
  1639.         {
  1640.             stunclk=160;
  1641.            
  1642.             if(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_brang))
  1643.             {
  1644.                 hp -= (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_brang))*DAMAGE_MULTIPLIER;
  1645.                 goto hitclock;
  1646.             }
  1647.            
  1648.             break;
  1649.         }
  1650.        
  1651.         if(!power)
  1652.             hp-=(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].fam_type : current_item(itype_brang))*DAMAGE_MULTIPLIER;
  1653.         else
  1654.             hp-=power;
  1655.            
  1656.         goto hitclock;
  1657.     }
  1658.    
  1659.     case wHookshot:
  1660.     {
  1661.         int def = defend(wpnId, &power, edefHOOKSHOT);
  1662.        
  1663.         if(def >= 0) return def;
  1664.        
  1665.         if(!(flags & guy_bhit))
  1666.         {
  1667.             stunclk=160;
  1668.            
  1669.             if(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_hookshot))
  1670.             {
  1671.                 hp -= (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_hookshot))*DAMAGE_MULTIPLIER;
  1672.                 goto hitclock;
  1673.             }
  1674.            
  1675.             break;
  1676.         }
  1677.        
  1678.         if(!power) hp-=(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].fam_type : current_item(itype_hookshot))*DAMAGE_MULTIPLIER;
  1679.         else
  1680.             hp-=power;
  1681.            
  1682.         goto hitclock;
  1683.     }
  1684.     break;
  1685.    
  1686.     case wHSHandle:
  1687.     {
  1688.         if(itemsbuf[enemyHitWeapon>-1 ? enemyHitWeapon : current_item_id(itype_hookshot)].flags & ITEM_FLAG1)
  1689.             return 0;
  1690.            
  1691.         bool ignorehookshot = ((defense[edefHOOKSHOT] == edIGNORE) || ((defense[edefHOOKSHOT] == edIGNOREL1 || defense[edefHOOKSHOT] == edSTUNORIGNORE)
  1692.                                && (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_hookshot)) <= 0));
  1693.                                
  1694.         // Peahats, Darknuts, Aquamentuses, Pols Voices, Wizzrobes, Manhandlas
  1695.         if(!(family==eePEAHAT || family==eeAQUA || family==eeMANHAN || (family==eeWIZZ && !ignorehookshot)
  1696.                 || (family==eeWALK && dmisc9==e9tPOLSVOICE) || (family==eeWALK && flags&(inv_back|inv_front|inv_left|inv_right))))
  1697.             return 0;
  1698.            
  1699.         power = DAMAGE_MULTIPLIER;
  1700.         //fallthrough
  1701.     }
  1702.    
  1703. fsparkle:
  1704.  
  1705.     default:
  1706.         // Work out the defenses!
  1707.     {
  1708.         int def = defenditemclass(wpnId, &power, w);
  1709.        
  1710.         if(def >= 0)
  1711.             return def;
  1712.         else if(def == -2)
  1713.         {
  1714.             ret = 0;
  1715.         }
  1716.     }
  1717.    
  1718.     if(!power)
  1719.     {
  1720.         if(flags & guy_bhit)
  1721.             hp-=1;
  1722.         else
  1723.         {
  1724.             // Don't make a long chain of 'stun' hits
  1725.             if((wpnId==wFire || wpnId==wBomb || wpnId==wSBomb || wpnId==wSword) && stunclk>0)
  1726.                 return 1;
  1727.                
  1728.             stunclk=160;
  1729.             break;
  1730.         }
  1731.     }
  1732.     else hp-=power;
  1733.    
  1734. hitclock:
  1735.     hclk=33;
  1736.    
  1737.     // Use w->dir instead of wpnDir to make sure boomerangs don't push enemies the wrong way
  1738.     if((dir&2)==(w->dir&2))
  1739.     {
  1740.         sclk=(w->dir<<8)+16;
  1741.     }
  1742.     }
  1743.    
  1744.     if(((wpnId==wBrang) || (get_bit(quest_rules,qr_NOFLASHDEATH))) && hp<=0)
  1745.     {
  1746.         fading=fade_blue_poof;
  1747.     }
  1748.    
  1749.     Backend::sfx->play(WAV_EHIT, int(x));
  1750.    
  1751.     if(hitsfx > 0)
  1752.         Backend::sfx->play(hitsfx, int(x));
  1753.        
  1754.     if(family==eeGUY)
  1755.         Backend::sfx->play(WAV_EDEAD, int(x));
  1756.        
  1757.     // Penetrating weapons
  1758.     if((wpnId==wArrow || wpnId==wBeam) && !cannotpenetrate())
  1759.     {
  1760.         int item=enemyHitWeapon;
  1761.        
  1762.         if(wpnId==wArrow)
  1763.         {
  1764.             if(item<0)
  1765.                 item=current_item_id(itype_arrow);
  1766.                
  1767.             if(item>=0 && (itemsbuf[item].flags&ITEM_FLAG1))
  1768.                 return 0;
  1769.         }
  1770.        
  1771.         else
  1772.         {
  1773.             if(item<0)
  1774.                 item=current_item_id(itype_sword);
  1775.                
  1776.             if(item>=0 && (itemsbuf[item].flags&ITEM_FLAG3))
  1777.                 return 0;
  1778.         }
  1779.     }
  1780.    
  1781.     return ret;
  1782. }
  1783.  
  1784. bool enemy::dont_draw()
  1785. {
  1786.     if(fading==fade_invisible || (((flags2&guy_blinking)||(fading==fade_flicker)) && (clk&1)))
  1787.         return true;
  1788.        
  1789.     if(flags&guy_invisible)
  1790.         return true;
  1791.        
  1792.     if(flags&lens_only && !lensclk)
  1793.         return true;
  1794.        
  1795.     return false;
  1796. }
  1797.  
  1798. // base drawing function to be used by all derived classes instead of
  1799. // sprite::draw()
  1800. void enemy::draw(BITMAP *dest)
  1801. {
  1802.     if(dont_draw())
  1803.         return;
  1804.        
  1805.     int cshold=cs;
  1806.    
  1807.     if(dying)
  1808.     {
  1809.         if(clk2>=19)
  1810.         {
  1811.             if(!(clk2&2))
  1812.                 sprite::draw(dest);
  1813.                
  1814.             return;
  1815.         }
  1816.        
  1817.         flip = 0;
  1818.         tile = wpnsbuf[iwDeath].tile;
  1819.        
  1820.         if(BSZ)
  1821.             tile += zc_min((15-clk2)/3,4);
  1822.         else if(clk2>6 && clk2<=12)
  1823.             ++tile;
  1824.            
  1825.         /* trying to get more death frames here
  1826.           if(wpnsbuf[wid].frames)
  1827.           {
  1828.           if(++clk2 >= wpnsbuf[wid].speed)
  1829.           {
  1830.           clk2 = 0;
  1831.           if(++aframe >= wpnsbuf[wid].frames)
  1832.           aframe = 0;
  1833.           }
  1834.           tile = wpnsbuf[wid].tile + aframe;
  1835.           }
  1836.           */
  1837.        
  1838.         if(BSZ || fading==fade_blue_poof)
  1839.             cs = wpnsbuf[iwDeath].csets&15;
  1840.         else
  1841.             cs = (((clk2+5)>>1)&3)+6;
  1842.     }
  1843.     else if(hclk>0)
  1844.     {
  1845.         if(family==eeGANON)
  1846.             cs=(((hclk-1)>>1)&3)+6;
  1847.         else if(hclk<33 && !get_bit(quest_rules,qr_ENEMIESFLICKER))
  1848.             cs=(((hclk-1)>>1)&3)+6;
  1849.     }
  1850.    
  1851.     if((tmpscr->flags3&fINVISROOM) &&
  1852.             !(current_item(itype_amulet)) &&
  1853.             !(get_bit(quest_rules,qr_LENSSEESENEMIES) &&
  1854.               lensclk) && family!=eeGANON)
  1855.     {
  1856.         sprite::drawcloaked(dest);
  1857.     }
  1858.     else
  1859.     {
  1860.         if(family !=eeGANON && hclk>0 && get_bit(quest_rules,qr_ENEMIESFLICKER))
  1861.         {
  1862.             if((frame&1)==1)
  1863.                 sprite::draw(dest);
  1864.         }
  1865.         else
  1866.             sprite::draw(dest);
  1867.     }
  1868.    
  1869.     cs=cshold;
  1870. }
  1871.  
  1872. // similar to the overblock function--can do up to a 32x32 sprite
  1873. void enemy::drawblock(BITMAP *dest,int mask)
  1874. {
  1875.     int thold=tile;
  1876.     int t1=tile;
  1877.     int t2=tile+20;
  1878.     int t3=tile+1;
  1879.     int t4=tile+21;
  1880.    
  1881.     switch(mask)
  1882.     {
  1883.     case 1:
  1884.         enemy::draw(dest);
  1885.         break;
  1886.        
  1887.     case 3:
  1888.         if(flip&2)
  1889.             zc_swap(t1,t2);
  1890.            
  1891.         tile=t1;
  1892.         enemy::draw(dest);
  1893.         tile=t2;
  1894.         yofs+=16;
  1895.         enemy::draw(dest);
  1896.         yofs-=16;
  1897.         break;
  1898.        
  1899.     case 5:
  1900.         t2=tile+1;
  1901.        
  1902.         if(flip&1)
  1903.             zc_swap(t1,t2);
  1904.            
  1905.         tile=t1;
  1906.         enemy::draw(dest);
  1907.         tile=t2;
  1908.         xofs+=16;
  1909.         enemy::draw(dest);
  1910.         xofs-=16;
  1911.         break;
  1912.        
  1913.     case 15:
  1914.         if(flip&1)
  1915.         {
  1916.             zc_swap(t1,t3);
  1917.             zc_swap(t2,t4);
  1918.         }
  1919.        
  1920.         if(flip&2)
  1921.         {
  1922.             zc_swap(t1,t2);
  1923.             zc_swap(t3,t4);
  1924.         }
  1925.        
  1926.         tile=t1;
  1927.         enemy::draw(dest);
  1928.         tile=t2;
  1929.         yofs+=16;
  1930.         enemy::draw(dest);
  1931.         yofs-=16;
  1932.         tile=t3;
  1933.         xofs+=16;
  1934.         enemy::draw(dest);
  1935.         tile=t4;
  1936.         yofs+=16;
  1937.         enemy::draw(dest);
  1938.         xofs-=16;
  1939.         yofs-=16;
  1940.         break;
  1941.     }
  1942.    
  1943.     tile=thold;
  1944. }
  1945.  
  1946. void enemy::drawshadow(BITMAP *dest, bool translucent)
  1947. {
  1948.     if(dont_draw() || tmpscr->flags7&fSIDEVIEW)
  1949.     {
  1950.         return;
  1951.     }
  1952.    
  1953.     if(dying)
  1954.     {
  1955.         return;
  1956.     }
  1957.    
  1958.     if(((tmpscr->flags3&fINVISROOM)&& !(current_item(itype_amulet)))||
  1959.             (darkroom))
  1960.     {
  1961.         return;
  1962.     }
  1963.     else
  1964.     {
  1965.         /*   if (canfall(id) && z>0)
  1966.              shadowtile = wpnsbuf[iwShadow].tile;
  1967.            sprite::drawshadow(dest,translucent);
  1968.            if (z==0)
  1969.              shadowtile = 0;*/
  1970.         // a bad idea, as enemies do their own setting of the shadow tile (since some use the
  1971.         // 2x2 tiles, shadows animate, etc.) -DD
  1972.        
  1973.         //this hack is in place as not all enemies that should use the z axis while in the air
  1974.         //(ie rocks, boulders) actually do. To be removed when the enemy revamp is complete -DD
  1975.         if(canfall(id) && shadowtile == 0)
  1976.             shadowtile = wpnsbuf[iwShadow].tile;
  1977.            
  1978.         if(z>0 || !canfall(id))
  1979.             sprite::drawshadow(dest,translucent);
  1980.     }
  1981. }
  1982.  
  1983. void enemy::masked_draw(BITMAP *dest,int mx,int my,int mw,int mh)
  1984. {
  1985.     BITMAP *sub=create_sub_bitmap(dest,mx,my,mw,mh);
  1986.    
  1987.     if(sub!=NULL)
  1988.     {
  1989.         xofs-=mx;
  1990.         yofs-=my;
  1991.         enemy::draw(sub);
  1992.         xofs+=mx;
  1993.         yofs+=my;
  1994.         destroy_bitmap(sub);
  1995.     }
  1996.     else
  1997.         enemy::draw(dest);
  1998. }
  1999.  
  2000. // override hit detection to check for invicibility, stunned, etc
  2001. bool enemy::hit(sprite *s)
  2002. {
  2003.     if(!(s->scriptcoldet&1)) return false;
  2004.    
  2005.     return (dying || hclk>0) ? false : sprite::hit(s);
  2006. }
  2007.  
  2008. bool enemy::hit(int tx,int ty,int tz,int txsz2,int tysz2,int tzsz2)
  2009. {
  2010.     return (dying || hclk>0) ? false : sprite::hit(tx,ty,tz,txsz2,tysz2,tzsz2);
  2011. }
  2012.  
  2013. bool enemy::hit(weapon *w)
  2014. {
  2015.     if(!(w->scriptcoldet&1)) return false;
  2016.    
  2017.     return (dying || hclk>0) ? false : sprite::hit(w);
  2018. }
  2019.  
  2020. //                         --==**==--
  2021.  
  2022. //   Movement routines that can be used by derived classes as needed
  2023.  
  2024. //                         --==**==--
  2025.  
  2026. void enemy::fix_coords(bool bound)
  2027. {
  2028.     if(bound)
  2029.     {
  2030.         x=vbound(x, 0, 240);
  2031.         y=vbound(y, 0, 160);
  2032.     }
  2033.    
  2034.     if(!OUTOFBOUNDS)
  2035.     {
  2036.         x=(fix)((int(x)&0xF0)+((int(x)&8)?16:0));
  2037.        
  2038.         if(tmpscr->flags7&fSIDEVIEW)
  2039.             y=(fix)((int(y)&0xF8)+((int(y)&4)?8:0));
  2040.         else
  2041.             y=(fix)((int(y)&0xF0)+((int(y)&8)?16:0));
  2042.     }
  2043. }
  2044.  
  2045. bool enemy::cannotpenetrate()
  2046. {
  2047.     return (family == eeAQUA || family == eeMANHAN || family == eeGHOMA);
  2048. }
  2049.  
  2050. // returns true if next step is ok, false if there is something there
  2051. bool enemy::canmove(int ndir,fix s,int special,int dx1,int dy1,int dx2,int dy2)
  2052. {
  2053.     bool ok;
  2054.     int dx = 0, dy = 0;
  2055.     int sv = 8;
  2056.     s += 0.5; // Make the ints round; doesn't seem to cause any problems.
  2057.    
  2058.     switch(ndir)
  2059.     {
  2060.     case 8:
  2061.     case up:
  2062.         if(canfall(id) && tmpscr->flags7&fSIDEVIEW)
  2063.             return false;
  2064.            
  2065.         dy = dy1-s;
  2066.         special = (special==spw_clipbottomright)?spw_none:special;
  2067.         ok = !m_walkflag(x,y+dy,special, x, y) && !flyerblocked(x,y+dy, special);
  2068.         break;
  2069.        
  2070.     case 12:
  2071.     case down:
  2072.         if(canfall(id) && tmpscr->flags7&fSIDEVIEW)
  2073.             return false;
  2074.            
  2075.         dy = dy2+s;
  2076.         ok = !m_walkflag(x,y+dy,special, x, y) && !flyerblocked(x,y+dy, special);
  2077.         break;
  2078.        
  2079.     case 14:
  2080.     case left:
  2081.         dx = dx1-s;
  2082.         sv = ((tmpscr->flags7&fSIDEVIEW)?7:8);
  2083.         special = (special==spw_clipbottomright||special==spw_clipright)?spw_none:special;
  2084.         ok = !m_walkflag(x+dx,y+sv,special, x, y) && !flyerblocked(x+dx,y+8, special);
  2085.         break;
  2086.        
  2087.     case 10:
  2088.     case right:
  2089.         dx = dx2+s;
  2090.         sv = ((tmpscr->flags7&fSIDEVIEW)?7:8);
  2091.         ok = !m_walkflag(x+dx,y+sv,special, x, y) && !flyerblocked(x+dx,y+8, special);
  2092.         break;
  2093.        
  2094.     case 9:
  2095.     case r_up:
  2096.         dx = dx2+s;
  2097.         dy = dy1-s;
  2098.         ok = !m_walkflag(x,y+dy,special, x, y) && !m_walkflag(x+dx,y+sv,special, x, y) &&
  2099.              !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special);
  2100.         break;
  2101.        
  2102.     case 11:
  2103.     case r_down:
  2104.         dx = dx2+s;
  2105.         dx = dy2+s;
  2106.         ok = !m_walkflag(x,y+dy,special, x, y) && !m_walkflag(x+dx,y+sv,special, x, y) &&
  2107.              !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special);
  2108.         break;
  2109.        
  2110.     case 13:
  2111.     case l_down:
  2112.         dx = dx1-s;
  2113.         dy = dy2+s;
  2114.         ok = !m_walkflag(x,y+dy,special, x, y) && !m_walkflag(x+dx,y+sv,special, x, y) &&
  2115.              !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special);
  2116.         break;
  2117.        
  2118.     case 15:
  2119.     case l_up:
  2120.         dx = dx1-s;
  2121.         dy = dy1-s;
  2122.         ok = !m_walkflag(x,y+dy,special, x, y) && !m_walkflag(x+dx,y+sv,special, x, y) &&
  2123.              !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special);
  2124.         break;
  2125.        
  2126.     default:
  2127.         db=99;
  2128.         return true;
  2129.     }
  2130.    
  2131.     return ok;
  2132. }
  2133.  
  2134.  
  2135. bool enemy::canmove(int ndir,fix s,int special)
  2136. {
  2137.     return canmove(ndir,s,special,0,-8,15,15);
  2138. }
  2139.  
  2140. bool enemy::canmove(int ndir,int special)
  2141. {
  2142.     bool dodongo_move=true; //yes, it's an ugly hack, but we're going to rewrite everything later anyway - DN
  2143.    
  2144.     if(special==spw_clipright&&ndir==right)
  2145.     {
  2146.         dodongo_move=canmove(ndir,(fix)1,special,0,-8,31,15);
  2147.     }
  2148.    
  2149.     return canmove(ndir,(fix)1,special,0,-8,15,15)&&dodongo_move;
  2150. }
  2151.  
  2152. bool enemy::canmove(int ndir)
  2153. {
  2154.     return canmove(ndir,(fix)1,spw_none,0,-8,15,15);
  2155. }
  2156.  
  2157. // 8-directional
  2158. void enemy::newdir_8(int newrate,int newhoming,int special,int dx1,int dy1,int dx2,int dy2)
  2159. {
  2160.     int ndir=0;
  2161.    
  2162.     // can move straight, check if it wants to turn
  2163.     if(canmove(dir,step,special,dx1,dy1,dx2,dy2))
  2164.     {
  2165.         if(grumble && (rand()&4)<grumble) //Homing
  2166.         {
  2167.             int w = Lwpns.idFirst(wBait);
  2168.            
  2169.             if(w>=0)
  2170.             {
  2171.                 int bx = Lwpns.spr(w)->x;
  2172.                 int by = Lwpns.spr(w)->y;
  2173.                
  2174.                 ndir = (bx<x) ? left : (bx!=x) ? right : 0;
  2175.                
  2176.                 if(abs(int(y)-by)>14)
  2177.                 {
  2178.                     if(ndir>0)  // Already left or right
  2179.                     {
  2180.                         // Making the diagonal directions
  2181.                         ndir += (by<y) ? 2 : 4;
  2182.                     }
  2183.                     else
  2184.                     {
  2185.                         ndir = (by<y) ? up : down;
  2186.                     }
  2187.                 }
  2188.                
  2189.                 if(canmove(ndir,special))
  2190.                 {
  2191.                     dir=ndir;
  2192.                     return;
  2193.                 }
  2194.             }
  2195.         }
  2196.        
  2197.         // Homing added.
  2198.         if(newhoming && (rand()&255)<newhoming)
  2199.         {
  2200.             ndir = lined_up(8,true);
  2201.            
  2202.             if(ndir>=0 && canmove(ndir,special))
  2203.             {
  2204.                 dir=ndir;
  2205.             }
  2206.            
  2207.             return;
  2208.         }
  2209.        
  2210.         int r=rand();
  2211.        
  2212.         if(newrate>0 && !(r%newrate))
  2213.         {
  2214.             ndir = ((dir+((r&64)?-1:1))&7)+8;
  2215.             int ndir2=((dir+((r&64)?1:-1))&7)+8;
  2216.            
  2217.             if(canmove(ndir,step,special,dx1,dy1,dx2,dy2))
  2218.                 dir=ndir;
  2219.             else if(canmove(ndir2,step,special,dx1,dy1,dx2,dy2))
  2220.                 dir=ndir2;
  2221.                
  2222.             if(dir==ndir && (newrate>=4)) // newrate>=4, otherwise movement is biased toward upper-left
  2223.                 // due to numerous lost fractional components. -L
  2224.             {
  2225.                 x.v&=0xFFFF0000;
  2226.                 y.v&=0xFFFF0000;
  2227.             }
  2228.         }
  2229.        
  2230.         return;
  2231.     }
  2232.    
  2233.     // can't move straight, must turn
  2234.     int i=0;
  2235.    
  2236.     for(; i<32; i++)  // Try random dir
  2237.     {
  2238.         ndir=(rand()&7)+8;
  2239.        
  2240.         if(canmove(ndir,step,special,dx1,dy1,dx2,dy2))
  2241.             break;
  2242.     }
  2243.    
  2244.     if(i==32)
  2245.     {
  2246.         for(ndir=8; ndir<16; ndir++)
  2247.         {
  2248.             if(canmove(ndir,step,special,dx1,dy1,dx2,dy2))
  2249.                 goto ok;
  2250.         }
  2251.        
  2252.         ndir = (tmpscr->flags7&fSIDEVIEW) ? (rand()&1 ? left : right) : -1;  // Sideview enemies get trapped if their dir becomes -1
  2253.     }
  2254.    
  2255. ok:
  2256.     dir=ndir;
  2257.     x.v&=0xFFFF0000;
  2258.     y.v&=0xFFFF0000;
  2259. }
  2260.  
  2261. void enemy::newdir_8(int newrate,int newhoming,int special)
  2262. {
  2263.     newdir_8(newrate,newhoming,special,0,-8,15,15);
  2264. }
  2265.  
  2266. // makes the enemy slide backwards when hit
  2267. // sclk: first byte is clk, second byte is dir
  2268. bool enemy::slide()
  2269. {
  2270.     if(sclk==0 || hp<=0)
  2271.         return false;
  2272.        
  2273.     if((sclk&255)==16 && !canmove(sclk>>8,(fix)12,0))
  2274.     {
  2275.         sclk=0;
  2276.         return false;
  2277.     }
  2278.    
  2279.     --sclk;
  2280.    
  2281.     switch(sclk>>8)
  2282.     {
  2283.     case up:
  2284.         if(y<=16)
  2285.         {
  2286.             sclk=0;
  2287.             return false;
  2288.         }
  2289.        
  2290.         break;
  2291.        
  2292.     case down:
  2293.         if(y>=160)
  2294.         {
  2295.             sclk=0;
  2296.             return false;
  2297.         }
  2298.        
  2299.         break;
  2300.        
  2301.     case left:
  2302.         if(x<=16)
  2303.         {
  2304.             sclk=0;
  2305.             return false;
  2306.         }
  2307.        
  2308.         break;
  2309.        
  2310.     case right:
  2311.         if(x>=240)
  2312.         {
  2313.             sclk=0;
  2314.             return false;
  2315.         }
  2316.        
  2317.         break;
  2318.     }
  2319.    
  2320.     switch(sclk>>8)
  2321.     {
  2322.     case up:
  2323.         y-=4;
  2324.         break;
  2325.        
  2326.     case down:
  2327.         y+=4;
  2328.         break;
  2329.        
  2330.     case left:
  2331.         x-=4;
  2332.         break;
  2333.        
  2334.     case right:
  2335.         x+=4;
  2336.         break;
  2337.     }
  2338.    
  2339.     if(!canmove(sclk>>8,(fix)0,0))
  2340.     {
  2341.         switch(sclk>>8)
  2342.         {
  2343.         case up:
  2344.         case down:
  2345.             if((int(y)&15) > 7)
  2346.                 y=(int(y)&0xF0)+16;
  2347.             else
  2348.                 y=(int(y)&0xF0);
  2349.                
  2350.             break;
  2351.            
  2352.         case left:
  2353.         case right:
  2354.             if((int(x)&15) > 7)
  2355.                 x=(int(x)&0xF0)+16;
  2356.             else
  2357.                 x=(int(x)&0xF0);
  2358.                
  2359.             break;
  2360.         }
  2361.        
  2362.         sclk=0;
  2363.         clk3=0;
  2364.     }
  2365.    
  2366.     if((sclk&255)==0)
  2367.         sclk=0;
  2368.        
  2369.     return true;
  2370. }
  2371.  
  2372. bool enemy::can_slide()
  2373. {
  2374.     if(sclk==0 || hp<=0)
  2375.         return false;
  2376.        
  2377.     if((sclk&255)==16 && !canmove(sclk>>8,(fix)12,0))
  2378.     {
  2379.         return false;
  2380.     }
  2381.    
  2382.     return true;
  2383. }
  2384.  
  2385. bool enemy::fslide()
  2386. {
  2387.     if(sclk==0 || hp<=0)
  2388.         return false;
  2389.        
  2390.     if((sclk&255)==16 && !canmove(sclk>>8,(fix)12,spw_floater))
  2391.     {
  2392.         sclk=0;
  2393.         return false;
  2394.     }
  2395.    
  2396.     --sclk;
  2397.    
  2398.     switch(sclk>>8)
  2399.     {
  2400.     case up:
  2401.         if(y<=16)
  2402.         {
  2403.             sclk=0;
  2404.             return false;
  2405.         }
  2406.        
  2407.         break;
  2408.        
  2409.     case down:
  2410.         if(y>=160)
  2411.         {
  2412.             sclk=0;
  2413.             return false;
  2414.         }
  2415.        
  2416.         break;
  2417.        
  2418.     case left:
  2419.         if(x<=16)
  2420.         {
  2421.             sclk=0;
  2422.             return false;
  2423.         }
  2424.        
  2425.         break;
  2426.        
  2427.     case right:
  2428.         if(x>=240)
  2429.         {
  2430.             sclk=0;
  2431.             return false;
  2432.         }
  2433.        
  2434.         break;
  2435.     }
  2436.    
  2437.     switch(sclk>>8)
  2438.     {
  2439.     case up:
  2440.         y-=4;
  2441.         break;
  2442.        
  2443.     case down:
  2444.         y+=4;
  2445.         break;
  2446.        
  2447.     case left:
  2448.         x-=4;
  2449.         break;
  2450.        
  2451.     case right:
  2452.         x+=4;
  2453.         break;
  2454.     }
  2455.    
  2456.     if(!canmove(sclk>>8,(fix)0,spw_floater))
  2457.     {
  2458.         switch(sclk>>8)
  2459.         {
  2460.         case up:
  2461.         case down:
  2462.             if((int(y)&15) > 7)
  2463.                 y=(int(y)&0xF0)+16;
  2464.             else
  2465.                 y=(int(y)&0xF0);
  2466.                
  2467.             break;
  2468.            
  2469.         case left:
  2470.         case right:
  2471.             if((int(x)&15) > 7)
  2472.                 x=(int(x)&0xF0)+16;
  2473.             else
  2474.                 x=(int(x)&0xF0);
  2475.                
  2476.             break;
  2477.         }
  2478.        
  2479.         sclk=0;
  2480.         clk3=0;
  2481.     }
  2482.    
  2483.     if((sclk&255)==0)
  2484.         sclk=0;
  2485.        
  2486.     return true;
  2487. }
  2488.  
  2489. // changes enemy's direction, checking restrictions
  2490. // rate:   0 = no random changes, 16 = always random change
  2491. // homing: 0 = none, 256 = always
  2492. // grumble 0 = none, 4 = strongest appetite
  2493. void enemy::newdir(int newrate,int newhoming,int special)
  2494. {
  2495.     int ndir=-1;
  2496.    
  2497.     if(grumble && (rand()&3)<grumble)
  2498.     {
  2499.         int w = Lwpns.idFirst(wBait);
  2500.        
  2501.         if(w>=0)
  2502.         {
  2503.             int bx = Lwpns.spr(w)->x;
  2504.             int by = Lwpns.spr(w)->y;
  2505.            
  2506.             if(abs(int(y)-by)>14)
  2507.             {
  2508.                 ndir = (by<y) ? up : down;
  2509.                
  2510.                 if(canmove(ndir,special))
  2511.                 {
  2512.                     dir=ndir;
  2513.                     return;
  2514.                 }
  2515.             }
  2516.            
  2517.             ndir = (bx<x) ? left : right;
  2518.            
  2519.             if(canmove(ndir,special))
  2520.             {
  2521.                 dir=ndir;
  2522.                 return;
  2523.             }
  2524.         }
  2525.     }
  2526.    
  2527.     if((rand()&255)<newhoming)
  2528.     {
  2529.         ndir = lined_up(8,false);
  2530.        
  2531.         if(ndir>=0 && canmove(ndir,special))
  2532.         {
  2533.             dir=ndir;
  2534.             return;
  2535.         }
  2536.     }
  2537.    
  2538.     int i=0;
  2539.    
  2540.     for(; i<32; i++)
  2541.     {
  2542.         int r=rand();
  2543.        
  2544.         if((r&15)<newrate)
  2545.             ndir=(r>>4)&3;
  2546.         else
  2547.             ndir=dir;
  2548.            
  2549.         if(canmove(ndir,special))
  2550.             break;
  2551.     }
  2552.    
  2553.     if(i==32)
  2554.     {
  2555.         for(ndir=0; ndir<4; ndir++)
  2556.         {
  2557.             if(canmove(ndir,special))
  2558.                 goto ok;
  2559.         }
  2560.        
  2561.         ndir = (tmpscr->flags7&fSIDEVIEW) ? (rand()&1 ? left : right) : -1; // Sideview enemies get trapped if their dir becomes -1
  2562.     }
  2563.    
  2564. ok:
  2565.     dir = ndir;
  2566. }
  2567.  
  2568. void enemy::newdir()
  2569. {
  2570.     newdir(4,0,spw_none);
  2571. }
  2572.  
  2573. fix enemy::distance_left()
  2574. {
  2575.     int a2=x.v>>16;
  2576.     int b2=y.v>>16;
  2577.    
  2578.     switch(dir)
  2579.     {
  2580.     case up:
  2581.         return (fix)(b2&0xF);
  2582.        
  2583.     case down:
  2584.         return (fix)(16-(b2&0xF));
  2585.        
  2586.     case left:
  2587.         return (fix)(a2&0xF);
  2588.        
  2589.     case right:
  2590.         return (fix)(16-(a2&0xF));
  2591.     }
  2592.    
  2593.     return (fix)0;
  2594. }
  2595.  
  2596. // keeps walking around
  2597. void enemy::constant_walk(int newrate,int newhoming,int special)
  2598. {
  2599.     if(slide())
  2600.         return;
  2601.        
  2602.     if(clk<0 || dying || stunclk || watch || ceiling)
  2603.         return;
  2604.        
  2605.     if(clk3<=0)
  2606.     {
  2607.         fix_coords(true);
  2608.         newdir(newrate,newhoming,special);
  2609.        
  2610.         if(step==0)
  2611.             clk3=0;
  2612.         else
  2613.             clk3=int(16.0/step);
  2614.     }
  2615.     else if(scored)
  2616.     {
  2617.         dir^=1;
  2618.         clk3=int(16.0/step)-clk3;
  2619.     }
  2620.    
  2621.     --clk3;
  2622.     move(step);
  2623. }
  2624.  
  2625. void enemy::constant_walk()
  2626. {
  2627.     constant_walk(4,0,spw_none);
  2628. }
  2629.  
  2630. int enemy::pos(int newx,int newy)
  2631. {
  2632.     return (newy<<8)+newx;
  2633. }
  2634.  
  2635. // for variable step rates
  2636. void enemy::variable_walk(int newrate,int newhoming,int special)
  2637. {
  2638.     if(slide())
  2639.         return;
  2640.        
  2641.     if(clk<0 || dying || stunclk || watch || step == 0 || ceiling)
  2642.         return;
  2643.        
  2644.     fix dx = (fix)0;
  2645.     fix dy = (fix)0;
  2646.    
  2647.     switch(dir)
  2648.     {
  2649.     case 8:
  2650.     case up:
  2651.         dy-=step;
  2652.         break;
  2653.        
  2654.     case 12:
  2655.     case down:
  2656.         dy+=step;
  2657.         break;
  2658.        
  2659.     case 14:
  2660.     case left:
  2661.         dx-=step;
  2662.         break;
  2663.        
  2664.     case 10:
  2665.     case right:
  2666.         dx+=step;
  2667.         break;
  2668.        
  2669.     case 15:
  2670.     case l_up:
  2671.         dx-=step;
  2672.         dy-=step;
  2673.         break;
  2674.        
  2675.     case 9:
  2676.     case r_up:
  2677.         dx+=step;
  2678.         dy-=step;
  2679.         break;
  2680.        
  2681.     case 13:
  2682.     case l_down:
  2683.         dx-=step;
  2684.         dy+=step;
  2685.         break;
  2686.        
  2687.     case 11:
  2688.     case r_down:
  2689.         dx+=step;
  2690.         dy+=step;
  2691.         break;
  2692.     }
  2693.    
  2694.     if(((int(x)&15)==0 && (int(y)&15)==0 && clk3!=pos(x,y)) ||
  2695.             m_walkflag(int(x+dx),int(y+dy), spw_halfstep))
  2696.     {
  2697.         fix_coords();
  2698.         newdir(newrate,newhoming,special);
  2699.         clk3=pos(x,y);
  2700.     }
  2701.    
  2702.     move(step);
  2703. }
  2704.  
  2705. // pauses for a while after it makes a complete move (to a new square)
  2706. void enemy::halting_walk(int newrate,int newhoming,int special,int newhrate, int haltcnt)
  2707. {
  2708.     if(sclk && clk2)
  2709.     {
  2710.         clk3=0;
  2711.     }
  2712.    
  2713.     if(slide() || clk<0 || dying || stunclk || watch || ceiling)
  2714.     {
  2715.         return;
  2716.     }
  2717.    
  2718.     if(clk2>0)
  2719.     {
  2720.         --clk2;
  2721.         return;
  2722.     }
  2723.    
  2724.     if(clk3<=0)
  2725.     {
  2726.         fix_coords(true);
  2727.         newdir(newrate,newhoming,special);
  2728.         clk3=int(16.0/step);
  2729.        
  2730.         if(clk2<0)
  2731.         {
  2732.             clk2=0;
  2733.         }
  2734.         else if((rand()&15)<newhrate)
  2735.         {
  2736.             clk2=haltcnt;
  2737.             return;
  2738.         }
  2739.     }
  2740.     else if(scored)
  2741.     {
  2742.         dir^=1;
  2743.        
  2744.         clk3=int(16.0/step)-clk3;
  2745.     }
  2746.    
  2747.     --clk3;
  2748.     move(step);
  2749. }
  2750.  
  2751. // 8-directional movement, aligns to 8 pixels
  2752. void enemy::constant_walk_8(int newrate,int newhoming,int special)
  2753. {
  2754.     if(clk<0 || dying || stunclk || watch || ceiling)
  2755.         return;
  2756.        
  2757.     if(clk3<=0)
  2758.     {
  2759.         newdir_8(newrate,newhoming,special);
  2760.         clk3=int(8.0/step);
  2761.     }
  2762.    
  2763.     --clk3;
  2764.     move(step);
  2765. }
  2766.  
  2767. void enemy::halting_walk_8(int newrate,int newhoming, int newclk,int special,int newhrate, int haltcnt)
  2768. {
  2769.     if(clk<0 || dying || stunclk || watch)
  2770.         return;
  2771.        
  2772.     if(!canmove(dir,step,special))
  2773.         clk3=0;
  2774.        
  2775.     if(clk2>0)
  2776.     {
  2777.         --clk2;
  2778.         return;
  2779.     }
  2780.    
  2781.     if(clk3<=0)
  2782.     {
  2783.         newdir_8(newrate,newhoming,special);
  2784.         clk3=newclk;
  2785.        
  2786.         if(clk2<0)
  2787.         {
  2788.             clk2=0;
  2789.         }
  2790.         else if((rand()&15)<newhrate)
  2791.         {
  2792.             newdir_8(newrate,newhoming,special);
  2793.             clk2=haltcnt;
  2794.             return;
  2795.         }
  2796.     }
  2797.    
  2798.     --clk3;
  2799.     move(step);
  2800. }
  2801.  
  2802. // 8-directional movement, no alignment
  2803. void enemy::variable_walk_8(int newrate,int newhoming, int newclk,int special)
  2804. {
  2805.     if(clk<0 || dying || stunclk || watch || ceiling)
  2806.         return;
  2807.        
  2808.     if(!canmove(dir,step,special))
  2809.         clk3=0;
  2810.        
  2811.     if(clk3<=0)
  2812.     {
  2813.         newdir_8(newrate,newhoming,special);
  2814.         clk3=newclk;
  2815.     }
  2816.    
  2817.     --clk3;
  2818.     move(step);
  2819. }
  2820.  
  2821. // same as above but with variable enemy size
  2822. void enemy::variable_walk_8(int newrate,int newhoming, int newclk,int special,int dx1,int dy1,int dx2,int dy2)
  2823. {
  2824.     if(clk<0 || dying || stunclk || watch || ceiling)
  2825.         return;
  2826.        
  2827.     if(!canmove(dir,step,special,dx1,dy1,dx2,dy2))
  2828.         clk3=0;
  2829.        
  2830.     if(clk3<=0)
  2831.     {
  2832.         newdir_8(newrate,newhoming,special,dx1,dy1,dx2,dy2);
  2833.         clk3=newclk;
  2834.     }
  2835.    
  2836.     --clk3;
  2837.     move(step);
  2838. }
  2839.  
  2840. // the variable speed floater movement
  2841. // ms is max speed
  2842. // ss is step speed
  2843. // s is step count
  2844. // p is pause count
  2845. // g is graduality :)
  2846.  
  2847. void enemy::floater_walk(int newrate,int newclk,fix ms,fix ss,int s,int p, int g)
  2848. {
  2849.     ++clk2;
  2850.    
  2851.     switch(movestatus)
  2852.     {
  2853.     case 0:                                                 // paused
  2854.         if(clk2>=p)
  2855.         {
  2856.             movestatus=1;
  2857.             clk2=0;
  2858.         }
  2859.        
  2860.         break;
  2861.        
  2862.     case 1:                                                 // speeding up
  2863.         if(clk2<g*s)
  2864.         {
  2865.             if(!((clk2-1)%g))
  2866.                 step+=ss;
  2867.         }
  2868.         else
  2869.         {
  2870.             movestatus=2;
  2871.             clk2=0;
  2872.         }
  2873.        
  2874.         break;
  2875.        
  2876.     case 2:                                                 // normal
  2877.         step=ms;
  2878.        
  2879.         if(clk2>48 && !(rand()%768))
  2880.         {
  2881.             step=ss*s;
  2882.             movestatus=3;
  2883.             clk2=0;
  2884.         }
  2885.        
  2886.         break;
  2887.        
  2888.     case 3:                                                 // slowing down
  2889.         if(clk2<=g*s)
  2890.         {
  2891.             if(!(clk2%g))
  2892.                 step-=ss;
  2893.         }
  2894.         else
  2895.         {
  2896.             movestatus=0;
  2897.             step=0;
  2898.             clk2=0;
  2899.         }
  2900.        
  2901.         break;
  2902.     }
  2903.    
  2904.     variable_walk_8(movestatus==2?newrate:0,homing,newclk,spw_floater);
  2905. }
  2906.  
  2907. void enemy::floater_walk(int newrate,int newclk,fix s)
  2908. {
  2909.     floater_walk(newrate,newclk,s,(fix)0.125,3,80,32);
  2910. }
  2911.  
  2912. // Checks if enemy is lined up with Link. If so, returns direction Link is
  2913. // at as compared to enemy. Returns -1 if not lined up. Range is inclusive.
  2914. int enemy::lined_up(int range, bool dir8)
  2915. {
  2916.     int lx = Link.getX();
  2917.     int ly = Link.getY();
  2918.    
  2919.     if(abs(lx-int(x))<=range)
  2920.     {
  2921.         if(ly<y)
  2922.         {
  2923.             return up;
  2924.         }
  2925.        
  2926.         return down;
  2927.     }
  2928.    
  2929.     if(abs(ly-int(y))<=range)
  2930.     {
  2931.         if(lx<x)
  2932.         {
  2933.             return left;
  2934.         }
  2935.        
  2936.         return right;
  2937.     }
  2938.    
  2939.     if(dir8)
  2940.     {
  2941.         if(abs(lx-x)-abs(ly-y)<=range)
  2942.         {
  2943.             if(ly<y)
  2944.             {
  2945.                 if(lx<x)
  2946.                 {
  2947.                     return l_up;
  2948.                 }
  2949.                 else
  2950.                 {
  2951.                     return r_up;
  2952.                 }
  2953.             }
  2954.             else
  2955.             {
  2956.                 if(lx<x)
  2957.                 {
  2958.                     return l_down;
  2959.                 }
  2960.                 else
  2961.                 {
  2962.                     return r_down;
  2963.                 }
  2964.             }
  2965.         }
  2966.     }
  2967.    
  2968.     return -1;
  2969. }
  2970.  
  2971. // returns true if Link is within 'range' pixels of the enemy
  2972. bool enemy::LinkInRange(int range)
  2973. {
  2974.     int lx = Link.getX();
  2975.     int ly = Link.getY();
  2976.     return abs(lx-int(x))<=range && abs(ly-int(y))<=range;
  2977. }
  2978.  
  2979. // place the enemy in line with Link (red wizzrobes)
  2980. void enemy::place_on_axis(bool floater, bool solid_ok)
  2981. {
  2982.     int lx=zc_min(zc_max(int(Link.getX())&0xF0,32),208);
  2983.     int ly=zc_min(zc_max(int(Link.getY())&0xF0,32),128);
  2984.     int pos2=rand()%23;
  2985.     int tried=0;
  2986.     bool last_resort,placed=false;
  2987.    
  2988.    
  2989.     do
  2990.     {
  2991.         if(pos2<14)
  2992.         {
  2993.             x=(pos2<<4)+16;
  2994.             y=ly;
  2995.         }
  2996.         else
  2997.         {
  2998.             x=lx;
  2999.             y=((pos2-14)<<4)+16;
  3000.         }
  3001.        
  3002.         // Don't commit to a last resort if position is out of bounds.
  3003.         last_resort= !(x<32 || y<32 || x>=224 || y>=144);
  3004.        
  3005.         if(abs(lx-int(x))>16 || abs(ly-int(y))>16)
  3006.         {
  3007.             // Red Wizzrobes should be able to appear on water, but not other
  3008.             // solid combos; however, they could appear on solid combos in 2.10,
  3009.             // and some quests depend on that.
  3010.             if((solid_ok || !m_walkflag(x,y,floater ? spw_water : spw_door))
  3011.                     && !flyerblocked(x,y,floater ? spw_floater : spw_door))
  3012.                 placed=true;
  3013.         }
  3014.        
  3015.         if(!placed && tried>=22 && last_resort)
  3016.         {
  3017.             placed=true;
  3018.         }
  3019.        
  3020.         ++tried;
  3021.         pos2=(pos2+3)%23;
  3022.     }
  3023.     while(!placed);
  3024.    
  3025.     if(y==ly)
  3026.         dir=(x<lx)?right:left;
  3027.     else
  3028.         dir=(y<ly)?down:up;
  3029.        
  3030.     clk2=tried;
  3031. }
  3032.  
  3033. void enemy::n_frame_n_dir(int frames, int ndir, int f4)
  3034. {
  3035.     int t = o_tile;
  3036.    
  3037.     // Darknuts, but also Wizzrobes and Wallmasters
  3038.     switch(family)
  3039.     {
  3040.     case eeWALK:
  3041.         if(dmisc9==e9tPOLSVOICE && clk2>=0)
  3042.         {
  3043.             tile=s_tile;
  3044.             t=s_tile;
  3045.         }
  3046.        
  3047.         break;
  3048.        
  3049.     case eeTRAP:
  3050.         if(dummy_int[1] && guysbuf[id].flags2 & eneflag_trp2)  // Just to make sure
  3051.         {
  3052.             tile=s_tile;
  3053.             t=s_tile;
  3054.         }
  3055.        
  3056.         break;
  3057.        
  3058.     case eeSPINTILE:
  3059.         if(misc>=96)
  3060.         {
  3061.             tile=o_tile+frames*ndir;
  3062.             t=tile;
  3063.         }
  3064.        
  3065.         break;
  3066.     }
  3067.    
  3068.     if(ndir!=0) switch(frames)
  3069.         {
  3070.         case 2:
  3071.             tiledir_small(dir,ndir==4);
  3072.             break;
  3073.            
  3074.         case 3:
  3075.             tiledir_three(dir);
  3076.             break;
  3077.            
  3078.         case 4:
  3079.             tiledir(dir,ndir==4);
  3080.             break;
  3081.         }
  3082.        
  3083.     if(family==eeWALK)
  3084.         tile=zc_min(tile+f4, t+frames*(zc_max(dir, 0)+1)-1);
  3085.     else
  3086.         tile+=f4;
  3087. }
  3088.  
  3089. void enemy::tiledir_three(int ndir)
  3090. {
  3091.     flip=0;
  3092.    
  3093.     switch(ndir)
  3094.     {
  3095.     case right:
  3096.         tile+=3; // fallthrough
  3097.        
  3098.     case left:
  3099.         tile+=3;  // fallthrough
  3100.        
  3101.     case down:
  3102.         tile+=3;  // fallthrough
  3103.        
  3104.     case up:
  3105.         break;
  3106.     }
  3107. }
  3108.  
  3109. void enemy::tiledir_small(int ndir, bool fourdir)
  3110. {
  3111.     flip=0;
  3112.    
  3113.     switch(ndir)
  3114.     {
  3115.     case 8:
  3116.     case up:
  3117.         break;
  3118.        
  3119.     case 12:
  3120.     case down:
  3121.         tile+=2;
  3122.         break;
  3123.        
  3124.     case 14:
  3125.     case left:
  3126.         tile+=4;
  3127.         break;
  3128.        
  3129.     case 10:
  3130.     case right:
  3131.         tile+=6;
  3132.         break;
  3133.        
  3134.     case 9:
  3135.     case r_up:
  3136.         if(fourdir)
  3137.             break;
  3138.            
  3139.         tile+=10;
  3140.         break;
  3141.        
  3142.     case 11:
  3143.     case r_down:
  3144.         if(fourdir)
  3145.             tile+=2;
  3146.         else
  3147.             tile+=14;
  3148.            
  3149.         break;
  3150.        
  3151.     case 13:
  3152.     case l_down:
  3153.         if(fourdir)
  3154.             tile+=2;
  3155.         else
  3156.             tile+=12;
  3157.            
  3158.         break;
  3159.        
  3160.     case 15:
  3161.     case l_up:
  3162.         if(fourdir)
  3163.             break;
  3164.            
  3165.         tile+=8;
  3166.         break;
  3167.        
  3168.     default:
  3169.         //dir=(rand()*100)%8;
  3170.         //tiledir_small(dir);
  3171.         //      flip=rand()&3;
  3172.         //      tile=(rand()*100000)%NEWMAXTILES;
  3173.         break;
  3174.     }
  3175. }
  3176.  
  3177. void enemy::tiledir(int ndir, bool fourdir)
  3178. {
  3179.     flip=0;
  3180.    
  3181.     switch(ndir)
  3182.     {
  3183.     case 8:
  3184.     case up:
  3185.         break;
  3186.        
  3187.     case 12:
  3188.     case down:
  3189.         tile+=4;
  3190.         break;
  3191.        
  3192.     case 14:
  3193.     case left:
  3194.         tile+=8;
  3195.         break;
  3196.        
  3197.     case 10:
  3198.     case right:
  3199.         tile+=12;
  3200.         break;
  3201.        
  3202.     case 9:
  3203.     case r_up:
  3204.         if(fourdir)
  3205.             break;
  3206.         else
  3207.             tile+=24;
  3208.            
  3209.         break;
  3210.        
  3211.     case 11:
  3212.     case r_down:
  3213.         if(fourdir)
  3214.             tile+=4;
  3215.         else
  3216.             tile+=32;
  3217.            
  3218.         break;
  3219.        
  3220.     case 13:
  3221.     case l_down:
  3222.         if(fourdir)
  3223.             tile+=4;
  3224.         else
  3225.             tile+=28;
  3226.            
  3227.         break;
  3228.        
  3229.     case 15:
  3230.     case l_up:
  3231.         if(fourdir)
  3232.             break;
  3233.         else
  3234.             tile+=20;
  3235.            
  3236.         break;
  3237.        
  3238.     default:
  3239.         //dir=(rand()*100)%8;
  3240.         //tiledir(dir);
  3241.         //      flip=rand()&3;
  3242.         //      tile=(rand()*100000)%NEWMAXTILES;
  3243.         break;
  3244.     }
  3245. }
  3246.  
  3247. void enemy::tiledir_big(int ndir, bool fourdir)
  3248. {
  3249.     flip=0;
  3250.    
  3251.     switch(ndir)
  3252.     {
  3253.     case 8:
  3254.     case up:
  3255.         break;
  3256.        
  3257.     case 12:
  3258.     case down:
  3259.         tile+=8;
  3260.         break;
  3261.        
  3262.     case 14:
  3263.     case left:
  3264.         tile+=40;
  3265.         break;
  3266.        
  3267.     case 10:
  3268.     case right:
  3269.         tile+=48;
  3270.         break;
  3271.        
  3272.     case 9:
  3273.     case r_up:
  3274.         if(fourdir)
  3275.             break;
  3276.            
  3277.         tile+=88;
  3278.         break;
  3279.        
  3280.     case 11:
  3281.     case r_down:
  3282.         if(fourdir)
  3283.             tile+=8;
  3284.         else
  3285.             tile+=128;
  3286.            
  3287.         break;
  3288.        
  3289.     case 13:
  3290.     case l_down:
  3291.         if(fourdir)
  3292.             tile+=8;
  3293.         else
  3294.             tile+=120;
  3295.            
  3296.         break;
  3297.        
  3298.     case 15:
  3299.     case l_up:
  3300.         if(fourdir)
  3301.             break;
  3302.            
  3303.         tile+=80;
  3304.         break;
  3305.        
  3306.     default:
  3307.         //dir=(rand()*100)%8;
  3308.         //tiledir_big(dir);
  3309.         //      flip=rand()&3;
  3310.         //      tile=(rand()*100000)%NEWMAXTILES;
  3311.         break;
  3312.     }
  3313. }
  3314.  
  3315. void enemy::update_enemy_frame()
  3316. {
  3317.     int newfrate = zc_max(frate,4);
  3318.     int f4=clk/(newfrate/4); // casts clk to [0,1,2,3]
  3319.     int f2=clk/(newfrate/2); // casts clk to [0,1]
  3320.     int fx = get_bit(quest_rules, qr_NEWENEMYTILES) ? f4 : f2;
  3321.     tile = o_tile;
  3322.     int tilerows = 1; // How many rows of tiles? The Extend code needs to know.
  3323.    
  3324.     switch(anim)
  3325.     {
  3326.     case aDONGO:
  3327.     {
  3328.         int fr = stunclk>0 ? 16 : 8;
  3329.        
  3330.         if(!dying && clk2>0 && clk2<=64)
  3331.         {
  3332.             // bloated
  3333.             switch(dir)
  3334.             {
  3335.             case up:
  3336.                 tile+=9;
  3337.                 flip=0;
  3338.                 xofs=0;
  3339.                 dummy_int[1]=0; //no additional tiles
  3340.                 break;
  3341.                
  3342.             case down:
  3343.                 tile+=7;
  3344.                 flip=0;
  3345.                 xofs=0;
  3346.                 dummy_int[1]=0; //no additional tiles
  3347.                 break;
  3348.                
  3349.             case left:
  3350.                 flip=1;
  3351.                 tile+=4;
  3352.                 xofs=16;
  3353.                 dummy_int[1]=1; //second tile is next tile
  3354.                 break;
  3355.                
  3356.             case right:
  3357.                 flip=0;
  3358.                 tile+=5;
  3359.                 xofs=16;
  3360.                 dummy_int[1]=-1; //second tile is previous tile
  3361.                 break;
  3362.             }
  3363.         }
  3364.         else if(!dying || clk2>19)
  3365.         {
  3366.             // normal
  3367.             switch(dir)
  3368.             {
  3369.             case up:
  3370.                 tile+=8;
  3371.                 flip=(clk&fr)?1:0;
  3372.                 xofs=0;
  3373.                 dummy_int[1]=0; //no additional tiles
  3374.                 break;
  3375.                
  3376.             case down:
  3377.                 tile+=6;
  3378.                 flip=(clk&fr)?1:0;
  3379.                 xofs=0;
  3380.                 dummy_int[1]=0; //no additional tiles
  3381.                 break;
  3382.                
  3383.             case left:
  3384.                 flip=1;
  3385.                 tile+=(clk&fr)?2:0;
  3386.                 xofs=16;
  3387.                 dummy_int[1]=1; //second tile is next tile
  3388.                 break;
  3389.                
  3390.             case right:
  3391.                 flip=0;
  3392.                 tile+=(clk&fr)?3:1;
  3393.                 xofs=16;
  3394.                 dummy_int[1]=-1; //second tile is next tile
  3395.                 break;
  3396.             }
  3397.         }
  3398.     }
  3399.     break;
  3400.    
  3401.     case aNEWDONGO:
  3402.     {
  3403.         int fr4=0;
  3404.        
  3405.         if(!dying && clk2>0 && clk2<=64)
  3406.         {
  3407.             // bloated
  3408.             if(clk2>=0)
  3409.             {
  3410.                 fr4=3;
  3411.             }
  3412.            
  3413.             if(clk2>=16)
  3414.             {
  3415.                 fr4=2;
  3416.             }
  3417.            
  3418.             if(clk2>=32)
  3419.             {
  3420.                 fr4=1;
  3421.             }
  3422.            
  3423.             if(clk2>=48)
  3424.             {
  3425.                 fr4=0;
  3426.             }
  3427.            
  3428.             switch(dir)
  3429.             {
  3430.             case up:
  3431.                 xofs=0;
  3432.                 tile+=8+fr4;
  3433.                 dummy_int[1]=0; //no additional tiles
  3434.                 break;
  3435.                
  3436.             case down:
  3437.                 xofs=0;
  3438.                 tile+=12+fr4;
  3439.                 dummy_int[1]=0; //no additional tiles
  3440.                 break;
  3441.                
  3442.             case left:
  3443.                 tile+=29+(2*fr4);
  3444.                 xofs=16;
  3445.                 dummy_int[1]=-1; //second tile is previous tile
  3446.                 break;
  3447.                
  3448.             case right:
  3449.                 tile+=49+(2*fr4);
  3450.                 xofs=16;
  3451.                 dummy_int[1]=-1; //second tile is previous tile
  3452.                 break;
  3453.             }
  3454.         }
  3455.         else if(!dying || clk2>19)
  3456.         {
  3457.             // normal
  3458.             switch(dir)
  3459.             {
  3460.             case up:
  3461.                 xofs=0;
  3462.                 tile+=((clk&12)>>2);
  3463.                 dummy_int[1]=0; //no additional tiles
  3464.                 break;
  3465.                
  3466.             case down:
  3467.                 xofs=0;
  3468.                 tile+=4+((clk&12)>>2);
  3469.                 dummy_int[1]=0; //no additional tiles
  3470.                 break;
  3471.                
  3472.             case left:
  3473.                 tile+=21+((clk&12)>>1);
  3474.                 xofs=16;
  3475.                 dummy_int[1]=-1; //second tile is previous tile
  3476.                 break;
  3477.                
  3478.             case right:
  3479.                 flip=0;
  3480.                 tile+=41+((clk&12)>>1);
  3481.                 xofs=16;
  3482.                 dummy_int[1]=-1; //second tile is previous tile
  3483.                 break;
  3484.             }
  3485.         }
  3486.     }
  3487.     break;
  3488.    
  3489.     case aDONGOBS:
  3490.     {
  3491.         int fr4=0;
  3492.        
  3493.         if(!dying && clk2>0 && clk2<=64)
  3494.         {
  3495.             // bloated
  3496.             if(clk2>=0)
  3497.             {
  3498.                 fr4=3;
  3499.             }
  3500.            
  3501.             if(clk2>=16)
  3502.             {
  3503.                 fr4=2;
  3504.             }
  3505.            
  3506.             if(clk2>=32)
  3507.             {
  3508.                 fr4=1;
  3509.             }
  3510.            
  3511.             if(clk2>=48)
  3512.             {
  3513.                 fr4=0;
  3514.             }
  3515.            
  3516.             switch(dir)
  3517.             {
  3518.             case up:
  3519.                 tile+=28+fr4;
  3520.                 yofs+=8;
  3521.                 dummy_int[1]=-20; //second tile change
  3522.                 dummy_int[2]=0;   //new xofs change
  3523.                 dummy_int[3]=-16; //new xofs change
  3524.                 break;
  3525.                
  3526.             case down:
  3527.                 tile+=12+fr4;
  3528.                 yofs-=8;
  3529.                 dummy_int[1]=20; //second tile change
  3530.                 dummy_int[2]=0;  //new xofs change
  3531.                 dummy_int[3]=16; //new xofs change
  3532.                 break;
  3533.                
  3534.             case left:
  3535.                 tile+=49+(2*fr4);
  3536.                 xofs+=8;
  3537.                 dummy_int[1]=-1; //second tile change
  3538.                 dummy_int[2]=-16; //new xofs change
  3539.                 dummy_int[3]=0;  //new xofs change
  3540.                 break;
  3541.                
  3542.             case right:
  3543.                 tile+=69+(2*fr4);
  3544.                 xofs+=8;
  3545.                 dummy_int[1]=-1; //second tile change
  3546.                 dummy_int[2]=-16; //new xofs change
  3547.                 dummy_int[3]=0;  //new xofs change
  3548.                 break;
  3549.             }
  3550.         }
  3551.         else if(!dying || clk2>19)
  3552.         {
  3553.             // normal
  3554.             switch(dir)
  3555.             {
  3556.             case up:
  3557.                 tile+=20+((clk&24)>>3);
  3558.                 yofs+=8;
  3559.                 dummy_int[1]=-20; //second tile change
  3560.                 dummy_int[2]=0;   //new xofs change
  3561.                 dummy_int[3]=-16; //new xofs change
  3562.                 break;
  3563.                
  3564.             case down:
  3565.                 tile+=4+((clk&24)>>3);
  3566.                 yofs-=8;
  3567.                 dummy_int[1]=20; //second tile change
  3568.                 dummy_int[2]=0;  //new xofs change
  3569.                 dummy_int[3]=16; //new xofs change
  3570.                 break;
  3571.                
  3572.             case left:
  3573.                 xofs=-8;
  3574.                 tile+=40+((clk&24)>>2);
  3575.                 dummy_int[1]=1; //second tile change
  3576.                 dummy_int[2]=16; //new xofs change
  3577.                 dummy_int[3]=0; //new xofs change
  3578.                 break;
  3579.                
  3580.             case right:
  3581.                 tile+=60+((clk&24)>>2);
  3582.                 xofs=-8;
  3583.                 dummy_int[1]=1; //second tile change
  3584.                 dummy_int[2]=16; //new xofs change
  3585.                 dummy_int[3]=0; //new xofs change
  3586.                 break;
  3587.             }
  3588.         }
  3589.     }
  3590.     break;
  3591.    
  3592.     case aWIZZ:
  3593.     {
  3594. //      if(d->misc1)
  3595.         if(dmisc1)
  3596.         {
  3597.             if(clk&8)
  3598.             {
  3599.                 ++tile;
  3600.             }
  3601.         }
  3602.         else
  3603.         {
  3604.             if(frame&4)
  3605.             {
  3606.                 ++tile;
  3607.             }
  3608.         }
  3609.        
  3610.         switch(dir)
  3611.         {
  3612.         case 9:
  3613.         case 15:
  3614.         case up:
  3615.             tile+=2;
  3616.             break;
  3617.            
  3618.         case down:
  3619.             break;
  3620.            
  3621.         case 13:
  3622.         case left:
  3623.             flip=1;
  3624.             break;
  3625.            
  3626.         default:
  3627.             flip=0;
  3628.             break;
  3629.         }
  3630.     }
  3631.     break;
  3632.    
  3633.     case aNEWWIZZ:
  3634.     {
  3635.         tiledir(dir,true);
  3636.        
  3637. //      if(d->misc1)                                            //walking wizzrobe
  3638.         if(dmisc1)                                            //walking wizzrobe
  3639.         {
  3640.             if(clk&8)
  3641.             {
  3642.                 tile+=2;
  3643.             }
  3644.            
  3645.             if(clk&4)
  3646.             {
  3647.                 tile+=1;
  3648.             }
  3649.            
  3650.             if(!(dummy_bool[1]||dummy_bool[2]))                               //should never be charging or firing for these wizzrobes
  3651.             {
  3652.                 if(dummy_int[1]>0)
  3653.                 {
  3654.                     tile+=40;
  3655.                 }
  3656.             }
  3657.         }
  3658.         else
  3659.         {
  3660.             if(dummy_bool[1]||dummy_bool[2])
  3661.             {
  3662.                 tile+=20;
  3663.                
  3664.                 if(dummy_bool[2])
  3665.                 {
  3666.                     tile+=20;
  3667.                 }
  3668.             }
  3669.            
  3670.             tile+=((frame>>1)&3);
  3671.         }
  3672.     }
  3673.     break;
  3674.    
  3675.     case a3FRM:
  3676.     {
  3677.         n_frame_n_dir(3, 0, (f4==3) ? 1 : f4);
  3678.     }
  3679.     break;
  3680.    
  3681.     case a3FRM4DIR:
  3682.     {
  3683.         n_frame_n_dir(3, 4, (f4==3) ? 1 : f4);
  3684.     }
  3685.     break;
  3686.    
  3687.     case aVIRE:
  3688.     {
  3689.         if(dir==up)
  3690.         {
  3691.             tile+=2;
  3692.         }
  3693.        
  3694.         tile+=fx;
  3695.     }
  3696.     break;
  3697.    
  3698.     case aROPE:
  3699.     {
  3700.         tile+=(1-fx);
  3701.         flip = dir==left ? 1:0;
  3702.     }
  3703.     break;
  3704.    
  3705.     case aZORA:
  3706.     {
  3707.         int dl;
  3708.        
  3709.         if(clk<36)
  3710.         {
  3711.             dl=clk+5;
  3712.             goto waves2;
  3713.         }
  3714.        
  3715.         if(clk<36+66)
  3716.             tile=(dir==up)?o_tile+1:o_tile;
  3717.         else
  3718.         {
  3719.             dl=clk-36-66;
  3720. waves2:
  3721.             tile=((dl/11)&1)+s_tile;
  3722.         }
  3723.     }
  3724.     break;
  3725.    
  3726.     case aNEWZORA:
  3727.     {
  3728.         f4=(clk/16)%4;
  3729.        
  3730.         tiledir(dir,true);
  3731.         int dl;
  3732.        
  3733.         if((clk>35)&&(clk<36+67))                               //surfaced
  3734.         {
  3735.             if((clk>=(35+10))&&(clk<(38+56)))                     //mouth open
  3736.             {
  3737.                 tile+=80;
  3738.             }                                                     //mouth closed
  3739.             else
  3740.             {
  3741.                 tile+=40;
  3742.             }
  3743.            
  3744.             tile+=f4;
  3745.         }
  3746.         else
  3747.         {
  3748.             if(clk<36)
  3749.             {
  3750.                 dl=clk+5;
  3751.             }
  3752.             else
  3753.             {
  3754.                 dl=clk-36-66;
  3755.             }
  3756.            
  3757.             tile+=((dl/5)&3);
  3758.         }
  3759.     }
  3760.     break;
  3761.    
  3762.     case a4FRM4EYE:
  3763.     case a2FRM4EYE:
  3764.     case a4FRM8EYE:
  3765.     {
  3766.         tilerows = 2;
  3767.         double ddir=atan2(double(y-(Link.y)),double(Link.x-x));
  3768.         int lookat=rand()&15;
  3769.        
  3770.         if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
  3771.         {
  3772.             lookat=l_down;
  3773.         }
  3774.         else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
  3775.         {
  3776.             lookat=down;
  3777.         }
  3778.         else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
  3779.         {
  3780.             lookat=r_down;
  3781.         }
  3782.         else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
  3783.         {
  3784.             lookat=right;
  3785.         }
  3786.         else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
  3787.         {
  3788.             lookat=r_up;
  3789.         }
  3790.         else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
  3791.         {
  3792.             lookat=up;
  3793.         }
  3794.         else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
  3795.         {
  3796.             lookat=l_up;
  3797.         }
  3798.         else
  3799.         {
  3800.             lookat=left;
  3801.         }
  3802.        
  3803.         int dir2 = dir;
  3804.         dir = lookat;
  3805.         n_frame_n_dir(anim==a2FRM4EYE ? 2:4, anim==a4FRM8EYE ? 8 : 4, anim==a2FRM4EYE ? (f2&1):f4);
  3806.         dir = dir2;
  3807.     }
  3808.     break;
  3809.    
  3810.     case aFLIP:
  3811.     {
  3812.         flip = f2&1;
  3813.     }
  3814.     break;
  3815.    
  3816.     case a2FRM:
  3817.     {
  3818.         tile += (1-f2);
  3819.     }
  3820.     break;
  3821.    
  3822.     case a2FRMB:
  3823.     {
  3824.         tile+= 2*(1-f2);
  3825.     }
  3826.     break;
  3827.    
  3828.     case a2FRM4DIR:
  3829.     {
  3830.         n_frame_n_dir(2, 4, f2&1);
  3831.     }
  3832.     break;
  3833.    
  3834.     case a4FRM4DIRF:
  3835.     {
  3836.         n_frame_n_dir(4,4,f4);
  3837.        
  3838.         if(clk2>0)                                              //stopped to fire
  3839.         {
  3840.             tile+=20;
  3841.            
  3842.             if(clk2<17)                                           //firing
  3843.             {
  3844.                 tile+=20;
  3845.             }
  3846.         }
  3847.     }
  3848.     break;
  3849.    
  3850.     case a4FRM4DIR:
  3851.     {
  3852.         n_frame_n_dir(4,4,f4);
  3853.     }
  3854.     break;
  3855.    
  3856.     case a4FRM8DIRF:
  3857.     {
  3858.         tilerows = 2;
  3859.         n_frame_n_dir(4,8,f4);
  3860.        
  3861.         if(clk2>0)                                              //stopped to fire
  3862.         {
  3863.             tile+=40;
  3864.            
  3865.             if(clk2<17)                                           //firing
  3866.             {
  3867.                 tile+=40;
  3868.             }
  3869.         }
  3870.     }
  3871.     break;
  3872.    
  3873.     case a4FRM8DIRB:
  3874.     {
  3875.         tilerows = 2;
  3876.         tiledir_big(dir,false);
  3877.         tile+=2*f4;
  3878.     }
  3879.     break;
  3880.    
  3881.     case aOCTO:
  3882.     {
  3883.         switch(dir)
  3884.         {
  3885.         case up:
  3886.             flip = 2;
  3887.             break;
  3888.            
  3889.         case down:
  3890.             flip = 0;
  3891.             break;
  3892.            
  3893.         case left:
  3894.             flip = 0;
  3895.             tile += 2;
  3896.             break;
  3897.            
  3898.         case right:
  3899.             flip = 1;
  3900.             tile += 2;
  3901.             break;
  3902.         }
  3903.        
  3904.         tile+=f2;
  3905.     }
  3906.     break;
  3907.    
  3908.     case aWALK:
  3909.     {
  3910.         switch(dir)
  3911.         {
  3912.         case up:
  3913.             tile+=3;
  3914.             flip = f2;
  3915.             break;
  3916.            
  3917.         case down:
  3918.             tile+=2;
  3919.             flip = f2;
  3920.             break;
  3921.            
  3922.         case left:
  3923.             flip=1;
  3924.             tile += f2;
  3925.             break;
  3926.            
  3927.         case right:
  3928.             flip=0;
  3929.             tile += f2;
  3930.             break;
  3931.         }
  3932.     }
  3933.     break;
  3934.    
  3935.     case aDWALK:
  3936.     {
  3937.         if((get_bit(quest_rules,qr_BRKNSHLDTILES)) && (dummy_bool[1]==true))
  3938.         {
  3939.             tile=s_tile;
  3940.         }
  3941.        
  3942.         switch(dir)
  3943.         {
  3944.         case up:
  3945.             tile+=2;
  3946.             flip=f2;
  3947.             break;
  3948.            
  3949.         case down:
  3950.             flip=0;
  3951.             tile+=(1-f2);
  3952.             break;
  3953.            
  3954.         case left:
  3955.             flip=1;
  3956.             tile+=(3+f2);
  3957.             break;
  3958.            
  3959.         case right:
  3960.             flip=0;
  3961.             tile+=(3+f2);
  3962.             break;
  3963.         }
  3964.     }
  3965.     break;
  3966.    
  3967.     case aTEK:
  3968.     {
  3969.         if(misc==0)
  3970.         {
  3971.             tile += f2;
  3972.         }
  3973.         else if(misc!=1)
  3974.         {
  3975.             ++tile;
  3976.         }
  3977.     }
  3978.     break;
  3979.    
  3980.     case aNEWTEK:
  3981.     {
  3982.         if(step<0)                                              //up
  3983.         {
  3984.             switch(clk3)
  3985.             {
  3986.             case left:
  3987.                 flip=0;
  3988.                 tile+=20;
  3989.                 break;
  3990.                
  3991.             case right:
  3992.                 flip=0;
  3993.                 tile+=24;
  3994.                 break;
  3995.             }
  3996.         }
  3997.         else if(step==0)
  3998.         {
  3999.             switch(clk3)
  4000.             {
  4001.             case left:
  4002.                 flip=0;
  4003.                 tile+=8;
  4004.                 break;
  4005.                
  4006.             case right:
  4007.                 flip=0;
  4008.                 tile+=12;
  4009.                 break;
  4010.             }
  4011.         }                                                       //down
  4012.         else
  4013.         {
  4014.             switch(clk3)
  4015.             {
  4016.             case left:
  4017.                 flip=0;
  4018.                 tile+=28;
  4019.                 break;
  4020.                
  4021.             case right:
  4022.                 flip=0;
  4023.                 tile+=32;
  4024.                 break;
  4025.             }
  4026.         }
  4027.        
  4028.         if(misc==0)
  4029.         {
  4030.             tile+=f4;
  4031.         }
  4032.         else if(misc!=1)
  4033.         {
  4034.             tile+=2;
  4035.         }
  4036.     }
  4037.     break;
  4038.    
  4039.     case aARMOS:
  4040.     {
  4041.         if(!fading)
  4042.         {
  4043.             tile += fx;
  4044.            
  4045.             if(dir==up)
  4046.                 tile += 2;
  4047.         }
  4048.     }
  4049.     break;
  4050.    
  4051.     case aARMOS4:
  4052.     {
  4053.         switch(dir)
  4054.         {
  4055.         case up:
  4056.             flip=0;
  4057.             break;
  4058.            
  4059.         case down:
  4060.             flip=0;
  4061.             tile+=4;
  4062.             break;
  4063.            
  4064.         case left:
  4065.             flip=0;
  4066.             tile+=8;
  4067.             break;
  4068.            
  4069.         case right:
  4070.             flip=0;
  4071.             tile+=12;
  4072.             break;
  4073.         }
  4074.        
  4075.         if(!fading)
  4076.         {
  4077.             tile+=f4;
  4078.         }
  4079.     }
  4080.     break;
  4081.    
  4082.     case aGHINI:
  4083.     {
  4084.         switch(dir)
  4085.         {
  4086.         case 8:
  4087.         case 9:
  4088.         case up:
  4089.             ++tile;
  4090.             flip=0;
  4091.             break;
  4092.            
  4093.         case 15:
  4094.             ++tile;
  4095.             flip=1;
  4096.             break;
  4097.            
  4098.         case 10:
  4099.         case 11:
  4100.         case right:
  4101.             flip=1;
  4102.             break;
  4103.            
  4104.         default:
  4105.             flip=0;
  4106.             break;
  4107.         }
  4108.     }
  4109.     break;
  4110.    
  4111.     case a2FRMPOS:
  4112.     {
  4113.         tile+=posframe;
  4114.     }
  4115.     break;
  4116.    
  4117.     case a4FRMPOS4DIR:
  4118.     {
  4119.         n_frame_n_dir(4,4,0);
  4120.         //        tile+=f2;
  4121.         tile+=posframe;
  4122.     }
  4123.     break;
  4124.    
  4125.     case a4FRMPOS4DIRF:
  4126.     {
  4127.         n_frame_n_dir(4,4,0);
  4128.        
  4129.         if(clk2>0)                                              //stopped to fire
  4130.         {
  4131.             tile+=20;
  4132.            
  4133.             if(clk2<17)                                           //firing
  4134.             {
  4135.                 tile+=20;
  4136.             }
  4137.         }
  4138.        
  4139.         //        tile+=f2;
  4140.         tile+=posframe;
  4141.     }
  4142.     break;
  4143.    
  4144.     case a4FRMPOS8DIR:
  4145.     {
  4146.         tilerows = 2;
  4147.         n_frame_n_dir(4,8,0);
  4148.         //        tile+=f2;
  4149.         tile+=posframe;
  4150.     }
  4151.     break;
  4152.    
  4153.     case a4FRMPOS8DIRF:
  4154.     {
  4155.         tilerows = 2;
  4156.         n_frame_n_dir(4,8,f4);
  4157.        
  4158.         if(clk2>0)                                              //stopped to fire
  4159.         {
  4160.             tile+=40;
  4161.            
  4162.             if(clk2<17)                                           //firing
  4163.             {
  4164.                 tile+=40;
  4165.             }
  4166.         }
  4167.        
  4168.         //        tile+=f2;
  4169.         tile+=posframe;
  4170.     }
  4171.     break;
  4172.    
  4173.     case aNEWLEV:
  4174.     {
  4175.         tiledir(dir,true);
  4176.        
  4177.         switch(misc)
  4178.         {
  4179.         case -1:
  4180.         case 0:
  4181.             return;
  4182.            
  4183.         case 1:
  4184.        
  4185. //        case 5: cs = d->misc2; break;
  4186.         case 5:
  4187.             cs = dmisc2;
  4188.             break;
  4189.            
  4190.         case 2:
  4191.         case 4:
  4192.             tile += 20;
  4193.             break;
  4194.            
  4195.         case 3:
  4196.             tile += 40;
  4197.             break;
  4198.         }
  4199.        
  4200.         tile+=f4;
  4201.     }
  4202.     break;
  4203.    
  4204.     case aLEV:
  4205.     {
  4206.         f4 = ((clk/5)&1);
  4207.        
  4208.         switch(misc)
  4209.         {
  4210.         case -1:
  4211.         case 0:
  4212.             return;
  4213.            
  4214.         case 1:
  4215.        
  4216. //        case 5: tile += (f2) ? 1 : 0; cs = d->misc2; break;
  4217.         case 5:
  4218.             tile += (f2) ? 1 : 0;
  4219.             cs = dmisc2;
  4220.             break;
  4221.            
  4222.         case 2:
  4223.         case 4:
  4224.             tile += 2;
  4225.             break;
  4226.            
  4227.         case 3:
  4228.             tile += (f4) ? 4 : 3;
  4229.             break;
  4230.         }
  4231.     }
  4232.     break;
  4233.    
  4234.     case aWALLM:
  4235.     {
  4236.         if(!dummy_bool[1])
  4237.         {
  4238.             tile += f2;
  4239.         }
  4240.     }
  4241.     break;
  4242.    
  4243.     case aNEWWALLM:
  4244.     {
  4245.         int tempdir=0;
  4246.        
  4247.         switch(misc)
  4248.         {
  4249.         case 1:
  4250.         case 2:
  4251.             tempdir=clk3;
  4252.             break;
  4253.            
  4254.         case 3:
  4255.         case 4:
  4256.         case 5:
  4257.             tempdir=dir;
  4258.             break;
  4259.            
  4260.         case 6:
  4261.         case 7:
  4262.             tempdir=clk3^1;
  4263.             break;
  4264.         }
  4265.        
  4266.         tiledir(tempdir,true);
  4267.        
  4268.         if(!dummy_bool[1])
  4269.         {
  4270.             tile+=f4;
  4271.         }
  4272.     }
  4273.     break;
  4274.    
  4275.     case a4FRMNODIR:
  4276.     {
  4277.         tile+=f4;
  4278.     }
  4279.     break;
  4280.    
  4281.     }                                                         // switch(d->anim)
  4282.    
  4283.     // flashing
  4284. //  if(d->flags2 & guy_flashing)
  4285.     if(flags2 & guy_flashing)
  4286.     {
  4287.         cs = (frame&3) + 6;
  4288.     }
  4289.    
  4290.     if(flags2&guy_transparent)
  4291.     {
  4292.         drawstyle=1;
  4293.     }
  4294.    
  4295.     int change = tile-o_tile;
  4296.    
  4297.     if(extend > 2)
  4298.     {
  4299.         if(o_tile/TILES_PER_ROW==(o_tile+((txsz*change)/tilerows))/TILES_PER_ROW)
  4300.         {
  4301.             tile=o_tile+txsz*change;
  4302.         }
  4303.         else
  4304.         {
  4305.             tile=o_tile+(txsz*change)+((tysz-1)*TILES_PER_ROW)*((o_tile+txsz*change)/TILES_PER_ROW)-(o_tile/TILES_PER_ROW);
  4306.         }
  4307.     }
  4308.     else
  4309.     {
  4310.         tile=o_tile+change;
  4311.     }
  4312. }
  4313.  
  4314. int wpnsfx(int wpn)
  4315. {
  4316.     switch(wpn)
  4317.     {
  4318.     case ewFireTrail:
  4319.     case ewFlame:
  4320.     case ewFlame2Trail:
  4321.     case ewFlame2:
  4322.         return WAV_FIRE;
  4323.        
  4324.     case ewWind:
  4325.     case ewMagic:
  4326.         return WAV_WAND;
  4327.        
  4328.     case ewIce:
  4329.         return WAV_ZN1ICE;
  4330.        
  4331.     case ewRock:
  4332.         if(get_bit(quest_rules,qr_MORESOUNDS)) return WAV_ZN1ROCK;
  4333.        
  4334.     case ewFireball2:
  4335.     case ewFireball:
  4336.         if(get_bit(quest_rules,qr_MORESOUNDS)) return WAV_ZN1FIREBALL;
  4337.     }
  4338.    
  4339.     return -1;
  4340. }
  4341.  
  4342. /********************************/
  4343. /*********  Guy Class  **********/
  4344. /********************************/
  4345.  
  4346. // good guys, fires, fairy, and other non-enemies
  4347. // based on enemy class b/c guys in dungeons act sort of like enemies
  4348. // also easier to manage all the guys this way
  4349. guy::guy(fix X,fix Y,int Id,int Clk,bool mg) : enemy(X,Y,Id,Clk)
  4350. {
  4351.     mainguy=mg;
  4352.     canfreeze=false;
  4353.     dir=down;
  4354.     yofs=playing_field_offset;
  4355.     hxofs=2;
  4356.     hzsz=8;
  4357.     hxsz=12;
  4358.     hysz=17;
  4359.    
  4360.     if(!superman && (!isdungeon() || id==gFAIRY || id==gFIRE || id==gZELDA))
  4361.     {
  4362.         superman = 1;
  4363.         hxofs=1000;
  4364.     }
  4365. }
  4366.  
  4367. bool guy::animate(int index)
  4368. {
  4369.     if(mainguy && clk==0 && misc==0)
  4370.     {
  4371.         setupscreen();
  4372.         misc = 1;
  4373.     }
  4374.    
  4375.     if(mainguy && fadeclk==0)
  4376.         return true;
  4377.        
  4378.     hp=256;                                                   // good guys never die...
  4379.    
  4380.     if(hclk && !clk2)
  4381.     {
  4382.         // but if they get hit...
  4383.         ++clk2;                                                 // only do this once
  4384.        
  4385.         if(!get_bit(quest_rules,qr_NOGUYFIRES))
  4386.         {
  4387.             addenemy(BSZ?64:72,68,eSHOOTFBALL,0);
  4388.             addenemy(BSZ?176:168,68,eSHOOTFBALL,0);
  4389.         }
  4390.     }
  4391.    
  4392.     return enemy::animate(index);
  4393. }
  4394.  
  4395. void guy::draw(BITMAP *dest)
  4396. {
  4397.     update_enemy_frame();
  4398.    
  4399.     if(!mainguy || fadeclk<0 || fadeclk&1)
  4400.         enemy::draw(dest);
  4401. }
  4402.  
  4403. /*******************************/
  4404. /*********   Enemies   *********/
  4405. /*******************************/
  4406.  
  4407. eFire::eFire(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  4408. {
  4409.     clk4=0;
  4410.     shield= (flags&(inv_left | inv_right | inv_back |inv_front)) != 0;
  4411.    
  4412.     // Spawn type
  4413.     if(flags & guy_fadeflicker)
  4414.     {
  4415.         clk=0;
  4416.         superman = 1;
  4417.         fading=fade_flicker;
  4418.         count_enemy=false;
  4419.         dir=down;
  4420.        
  4421.         if(!canmove(down,(fix)8,spw_none))
  4422.             clk3=int(13.0/step);
  4423.     }
  4424.     else if(flags & guy_fadeinstant)
  4425.     {
  4426.         clk=0;
  4427.     }
  4428. }
  4429.  
  4430. bool eFire::animate(int index)
  4431. {
  4432.     if(fading)
  4433.     {
  4434.         if(++clk4 > 60)
  4435.         {
  4436.             clk4=0;
  4437.             superman=0;
  4438.             fading=0;
  4439.            
  4440.             if(flags2&cmbflag_armos && z==0)
  4441.                 removearmos(x,y);
  4442.                
  4443.             clk2=0;
  4444.            
  4445.             if(!canmove(down,(fix)8,spw_none))
  4446.             {
  4447.                 dir=0;
  4448.                 y.v&=0xF00000;
  4449.             }
  4450.            
  4451.             return Dead(index);
  4452.         }
  4453.         else if(flags2&cmbflag_armos && z==0 && clk==0)
  4454.             removearmos(x,y);
  4455.     }
  4456.    
  4457.     return enemy::animate(index);
  4458. }
  4459.  
  4460. void eFire::draw(BITMAP *dest)
  4461. {
  4462.     update_enemy_frame();
  4463.     enemy::draw(dest);
  4464. }
  4465.  
  4466. int eFire::takehit(weapon *w)
  4467. {
  4468.     int wpnId = w->id;
  4469.     int wpnDir = w->dir;
  4470.    
  4471.     if(wpnId==wHammer && shield && (flags & guy_bkshield)
  4472.             && ((flags&inv_front && wpnDir==(dir^down)) || (flags&inv_back && wpnDir==(dir^up))
  4473.                 || (flags&inv_left && wpnDir==(dir^left)) || (flags&inv_right && wpnDir==(dir^right))))
  4474.     {
  4475.         shield = false;
  4476.         flags &= ~(inv_left|inv_right|inv_back|inv_front);
  4477.        
  4478.         if(get_bit(quest_rules,qr_BRKNSHLDTILES))
  4479.             o_tile=s_tile;
  4480.     }
  4481.    
  4482.     int ret = enemy::takehit(w);
  4483.     return ret;
  4484. }
  4485.  
  4486. void eFire::break_shield()
  4487. {
  4488.     if(!shield)
  4489.         return;
  4490.        
  4491.     flags&=~(inv_front | inv_back | inv_left | inv_right);
  4492.     shield=false;
  4493.    
  4494.     if(get_bit(quest_rules,qr_BRKNSHLDTILES))
  4495.         o_tile=s_tile;
  4496. }
  4497.  
  4498. eOther::eOther(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  4499. {
  4500.     clk4=0;
  4501.     shield= (flags&(inv_left | inv_right | inv_back |inv_front)) != 0;
  4502.    
  4503.     // Spawn type
  4504.     if(flags & guy_fadeflicker)
  4505.     {
  4506.         clk=0;
  4507.         superman = 1;
  4508.         fading=fade_flicker;
  4509.         count_enemy=false;
  4510.         dir=down;
  4511.        
  4512.         if(!canmove(down,(fix)8,spw_none))
  4513.             clk3=int(13.0/step);
  4514.     }
  4515.     else if(flags & guy_fadeinstant)
  4516.     {
  4517.         clk=0;
  4518.     }
  4519. }
  4520.  
  4521. bool eOther::animate(int index)
  4522. {
  4523.     if(fading)
  4524.     {
  4525.         if(++clk4 > 60)
  4526.         {
  4527.             clk4=0;
  4528.             superman=0;
  4529.             fading=0;
  4530.            
  4531.             if(flags2&cmbflag_armos && z==0)
  4532.                 removearmos(x,y);
  4533.                
  4534.             clk2=0;
  4535.            
  4536.             if(!canmove(down,(fix)8,spw_none))
  4537.             {
  4538.                 dir=0;
  4539.                 y.v&=0xF00000;
  4540.             }
  4541.            
  4542.             return Dead(index);
  4543.         }
  4544.         else if(flags2&cmbflag_armos && z==0 && clk==0)
  4545.             removearmos(x,y);
  4546.     }
  4547.    
  4548.     return enemy::animate(index);
  4549. }
  4550.  
  4551. void eOther::draw(BITMAP *dest)
  4552. {
  4553.     update_enemy_frame();
  4554.     enemy::draw(dest);
  4555. }
  4556.  
  4557. int eOther::takehit(weapon *w)
  4558. {
  4559.     int wpnId = w->id;
  4560.     int wpnDir = w->dir;
  4561.    
  4562.     if(wpnId==wHammer && shield && (flags & guy_bkshield)
  4563.             && ((flags&inv_front && wpnDir==(dir^down)) || (flags&inv_back && wpnDir==(dir^up))
  4564.                 || (flags&inv_left && wpnDir==(dir^left)) || (flags&inv_right && wpnDir==(dir^right))))
  4565.     {
  4566.         shield = false;
  4567.         flags &= ~(inv_left|inv_right|inv_back|inv_front);
  4568.        
  4569.         if(get_bit(quest_rules,qr_BRKNSHLDTILES))
  4570.             o_tile=s_tile;
  4571.     }
  4572.    
  4573.     int ret = enemy::takehit(w);
  4574.     return ret;
  4575. }
  4576.  
  4577. void eOther::break_shield()
  4578. {
  4579.     if(!shield)
  4580.         return;
  4581.        
  4582.     flags&=~(inv_front | inv_back | inv_left | inv_right);
  4583.     shield=false;
  4584.    
  4585.     if(get_bit(quest_rules,qr_BRKNSHLDTILES))
  4586.         o_tile=s_tile;
  4587. }
  4588.  
  4589. void enemy::removearmos(int ax,int ay)
  4590. {
  4591.     if(did_armos)
  4592.     {
  4593.         return;
  4594.     }
  4595.    
  4596.     did_armos=true;
  4597.     ax&=0xF0;
  4598.     ay&=0xF0;
  4599.     int cd = (ax>>4)+ay;
  4600.     int f = MAPFLAG(ax,ay);
  4601.     int f2 = MAPCOMBOFLAG(ax,ay);
  4602.    
  4603.     if(combobuf[tmpscr->data[cd]].type!=cARMOS)
  4604.     {
  4605.         return;
  4606.     }
  4607.    
  4608.     tmpscr->data[cd] = tmpscr->undercombo;
  4609.     tmpscr->cset[cd] = tmpscr->undercset;
  4610.     tmpscr->sflag[cd] = 0;
  4611.    
  4612.     if(f == mfARMOS_SECRET || f2 == mfARMOS_SECRET)
  4613.     {
  4614.         tmpscr->data[cd] = tmpscr->secretcombo[sSTAIRS];
  4615.         tmpscr->cset[cd] = tmpscr->secretcset[sSTAIRS];
  4616.         tmpscr->sflag[cd]=tmpscr->secretflag[sSTAIRS];
  4617.         Backend::sfx->play(tmpscr->secretsfx,128);
  4618.     }
  4619.    
  4620.     if(f == mfARMOS_ITEM || f2 == mfARMOS_ITEM)
  4621.     {
  4622.         if(!getmapflag())
  4623.         {
  4624.             additem(ax,ay,tmpscr->catchall, (ipONETIME2 + ipBIGRANGE) | ((tmpscr->flags3&fHOLDITEM) ? ipHOLDUP : 0));
  4625.             Backend::sfx->play(tmpscr->secretsfx,128);
  4626.         }
  4627.     }
  4628.    
  4629.     putcombo(scrollbuf,ax,ay,tmpscr->data[cd],tmpscr->cset[cd]);
  4630. }
  4631.  
  4632. eGhini::eGhini(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  4633. {
  4634.     fading=fade_flicker;
  4635.     count_enemy=false;
  4636.     dir=12;
  4637.     movestatus=1;
  4638.     step=0;
  4639.     clk=0;
  4640.     clk4=0;
  4641. }
  4642.  
  4643. bool eGhini::animate(int index)
  4644. {
  4645.     if(dying)
  4646.         return Dead(index);
  4647.        
  4648.     if(dmisc1)
  4649.     {
  4650.         if(misc)
  4651.         {
  4652.             if(clk4>160)
  4653.                 misc=2;
  4654.                
  4655.             floater_walk((misc==1)?0:rate,hrate,dstep/100.0,dstep/1000.0,10,120,10);
  4656.             removearmos(x,y);
  4657.         }
  4658.         else if(clk4>=60)
  4659.         {
  4660.             misc=1;
  4661.             clk3=32;
  4662.             fading=0;
  4663.             guygrid[(int(y)&0xF0)+(int(x)>>4)]=0;
  4664.             removearmos(x,y);
  4665.         }
  4666.     }
  4667.    
  4668.     clk4++;
  4669.    
  4670.     return enemy::animate(index);
  4671. }
  4672.  
  4673. void eGhini::draw(BITMAP *dest)
  4674. {
  4675.     update_enemy_frame();
  4676.     enemy::draw(dest);
  4677. }
  4678.  
  4679. void eGhini::kickbucket()
  4680. {
  4681.     hp=-1000;                                                 // don't call death_sfx()
  4682. }
  4683.  
  4684. eTektite::eTektite(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  4685. {
  4686.     old_y=y;
  4687.     dir=down;
  4688.     misc=1;
  4689.     clk=-15;
  4690.    
  4691.     if(!BSZ)
  4692.         clk*=rand()%3+1;
  4693.        
  4694.     // avoid divide by 0 errors
  4695.     if(dmisc1 == 0)
  4696.         dmisc1 = 24;
  4697.        
  4698.     if(dmisc2 == 0)
  4699.         dmisc2 = 3;
  4700.        
  4701.     //nets+760;
  4702. }
  4703.  
  4704. bool eTektite::animate(int index)
  4705. {
  4706.     if(dying)
  4707.         return Dead(index);
  4708.        
  4709.     if(clk==0)
  4710.     {
  4711.         removearmos(x,y);
  4712.     }
  4713.    
  4714.     if(get_bit(quest_rules,qr_ENEMIESZAXIS))
  4715.     {
  4716.         y=floor_y;
  4717.     }
  4718.    
  4719.     if(clk>=0 && !stunclk && (!watch || misc==0))
  4720.     {
  4721.         switch(misc)
  4722.         {
  4723.         case 0:                                               // normal
  4724.             if(!(rand()%dmisc1))
  4725.             {
  4726.                 misc=1;
  4727.                 clk2=32;
  4728.             }
  4729.            
  4730.             break;
  4731.            
  4732.         case 1:                                               // waiting to pounce
  4733.             if(--clk2<=0)
  4734.             {
  4735.                 int r=rand();
  4736.                 misc=2;
  4737.                 step=0-((dstep)/100.0);                           // initial speed
  4738.                 clk3=(r&1)+2;                                       // left or right
  4739.                 clk2start=clk2=(r&31)+10;                           // flight time
  4740.                
  4741.                 if(y<32)  clk2+=2;                                  // make them come down from top of screen
  4742.                
  4743.                 if(y>112) clk2-=2;                                  // make them go back up
  4744.                
  4745.                 cstart=c = 9-((r&31)>>3);                           // time before gravity kicks in
  4746.             }
  4747.            
  4748.             break;
  4749.            
  4750.         case 2:                                                 // in flight
  4751.             move(step);
  4752.            
  4753.             if(step>0)                                            //going down
  4754.             {
  4755.                 if(COMBOTYPE(x+8,y+16)==cNOJUMPZONE)
  4756.                 {
  4757.                     step=0-step;
  4758.                 }
  4759.                 else if(COMBOTYPE(x+8,y+16)==cNOENEMY)
  4760.                 {
  4761.                     step=0-step;
  4762.                 }
  4763.                 else if(MAPFLAG(x+8,y+16)==mfNOENEMY)
  4764.                 {
  4765.                     step=0-step;
  4766.                 }
  4767.                 else if(MAPCOMBOFLAG(x+8,y+16)==mfNOENEMY)
  4768.                 {
  4769.                     step=0-step;
  4770.                 }
  4771.             }
  4772.             else if(step<0)
  4773.             {
  4774.                 if(COMBOTYPE(x+8,y)==cNOJUMPZONE)
  4775.                 {
  4776.                     step=0-step;
  4777.                 }
  4778.                 else if(COMBOTYPE(x+8,y)==cNOENEMY)
  4779.                 {
  4780.                     step=0-step;
  4781.                 }
  4782.                 else if(MAPFLAG(x+8,y)==mfNOENEMY)
  4783.                 {
  4784.                     step=0-step;
  4785.                 }
  4786.                 else if(MAPCOMBOFLAG(x+8,y)==mfNOENEMY)
  4787.                 {
  4788.                     step=0-step;
  4789.                 }
  4790.             }
  4791.            
  4792.             if(clk3==left)
  4793.             {
  4794.                 if(COMBOTYPE(x,y+8)==cNOJUMPZONE)
  4795.                 {
  4796.                     clk3^=1;
  4797.                 }
  4798.                 else if(COMBOTYPE(x,y+8)==cNOENEMY)
  4799.                 {
  4800.                     clk3^=1;
  4801.                 }
  4802.                 else if(MAPFLAG(x,y+8)==mfNOENEMY)
  4803.                 {
  4804.                     clk3^=1;
  4805.                 }
  4806.                 else if(MAPCOMBOFLAG(x,y+8)==mfNOENEMY)
  4807.                 {
  4808.                     clk3^=1;
  4809.                 }
  4810.             }
  4811.             else
  4812.             {
  4813.                 if(COMBOTYPE(x+16,y+8)==cNOJUMPZONE)
  4814.                 {
  4815.                     clk3^=1;
  4816.                 }
  4817.                 else if(COMBOTYPE(x+16,y+8)==cNOENEMY)
  4818.                 {
  4819.                     clk3^=1;
  4820.                 }
  4821.                 else if(MAPFLAG(x+16,y+8)==mfNOENEMY)
  4822.                 {
  4823.                     clk3^=1;
  4824.                 }
  4825.                 else if(MAPCOMBOFLAG(x+16,y+8)==mfNOENEMY)
  4826.                 {
  4827.                     clk3^=1;
  4828.                 }
  4829.             }
  4830.            
  4831.             --c;
  4832.            
  4833.             if(c<0 && step<(dstep/100.0))
  4834.             {
  4835.                 step+=(dmisc3/100.0);
  4836.             }
  4837.            
  4838.             int nb=get_bit(quest_rules,qr_NOBORDER) ? 16 : 0;
  4839.            
  4840.             if(x<=16-nb)  clk3=right;
  4841.            
  4842.             if(x>=224+nb) clk3=left;
  4843.            
  4844.             x += (clk3==left) ? -1 : 1;
  4845.            
  4846.             if((--clk2<=0 && y>=16-nb) || y>=144+nb)
  4847.             {
  4848.                 if(y>=144+nb && get_bit(quest_rules,qr_ENEMIESZAXIS))
  4849.                 {
  4850.                     step=0-step;
  4851.                     y--;
  4852.                 }
  4853.                 else if(rand()%dmisc2)                                 //land and wait
  4854.                 {
  4855.                     clk=misc=0;
  4856.                 }                                                   //land and jump again
  4857.                 else
  4858.                 {
  4859.                     misc=1;
  4860.                     clk2=0;
  4861.                 }
  4862.             }
  4863.            
  4864.             break;
  4865.         }                                                         // switch
  4866.     }
  4867.    
  4868.     if(get_bit(quest_rules,qr_ENEMIESZAXIS) && misc==2)
  4869.     {
  4870.         int tempy = floor_y;
  4871.         z=zc_max(0,zc_min(clk2start-clk2,clk2));
  4872.         floor_y = y;
  4873.         y=tempy-z;
  4874.         old_y = y;
  4875.     }
  4876.    
  4877.     if(stunclk && (clk&31)==1)
  4878.         clk=0;
  4879.        
  4880.     return enemy::animate(index);
  4881. }
  4882.  
  4883. void eTektite::drawshadow(BITMAP *dest,bool translucent)
  4884. {
  4885.     if(z<1 && get_bit(quest_rules,qr_ENEMIESZAXIS))
  4886.         return;
  4887.        
  4888.     int tempy=yofs;
  4889.     int fdiv = frate/4;
  4890.     int efrate = fdiv == 0 ? 0 : clk/fdiv;
  4891.     int f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
  4892.            efrate:((clk>=(frate>>1))?1:0);
  4893.     flip = 0;
  4894.     shadowtile = wpnsbuf[iwShadow].tile;
  4895.    
  4896.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  4897.     {
  4898.         if(misc==0)
  4899.         {
  4900.             shadowtile+=f2;
  4901.         }
  4902.         else if(misc!=1)
  4903.             shadowtile+=2;
  4904.     }
  4905.     else
  4906.     {
  4907.         if(misc==0)
  4908.         {
  4909.             shadowtile += f2 ? 1 : 0;
  4910.         }
  4911.         else if(misc!=1)
  4912.         {
  4913.             ++shadowtile;
  4914.         }
  4915.     }
  4916.    
  4917.     yofs+=8;
  4918.    
  4919.     if(!get_bit(quest_rules,qr_ENEMIESZAXIS) && misc==2)
  4920.     {
  4921.         yofs+=zc_max(0,zc_min(clk2start-clk2,clk2));
  4922.     }
  4923.    
  4924.     enemy::drawshadow(dest,translucent);
  4925.     yofs=tempy;
  4926. }
  4927.  
  4928. void eTektite::draw(BITMAP *dest)
  4929. {
  4930.     update_enemy_frame();
  4931.     enemy::draw(dest);
  4932. }
  4933.  
  4934. eItemFairy::eItemFairy(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  4935. {
  4936.     step=(fix)(guysbuf[id&0xFFF].step)/100;
  4937.     superman=1;
  4938.     dir=8;
  4939.     hxofs=1000;
  4940.     mainguy=false;
  4941.     count_enemy=false;
  4942. }
  4943.  
  4944. bool eItemFairy::animate(int index)
  4945. {
  4946.     if(dying)
  4947.         return Dead(index);
  4948.        
  4949.     //if(clk>32)
  4950.     misc=1;
  4951.     bool w=watch;
  4952.     watch=false;
  4953.     variable_walk_8(misc?3:0,0,8,spw_floater);
  4954.     watch=w;
  4955.    
  4956.     if(clk==0)
  4957.     {
  4958.         removearmos(x,y);
  4959.     }
  4960.    
  4961.     return enemy::animate(index);
  4962. }
  4963.  
  4964. void eItemFairy::draw(BITMAP *dest)
  4965. {
  4966.     //these are here to bypass compiler warnings about unused arguments
  4967.     dest=dest;
  4968. }
  4969.  
  4970. ePeahat::ePeahat(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  4971. {
  4972.     //floater_walk(int rate,int newclk,fix ms,fix ss,int s,int p, int g)
  4973.     floater_walk(misc?rate:0,      hrate, dstep/100.0,dstep/1000.0, 10,  80, 16);
  4974.     dir=8;
  4975.     movestatus=1;
  4976.     clk=0;
  4977.     step=0;
  4978.     //nets+720;
  4979. }
  4980.  
  4981. bool ePeahat::animate(int index)
  4982. {
  4983.     if(slide())
  4984.     {
  4985.         return false;
  4986.     }
  4987.    
  4988.     if(dying)
  4989.         return Dead(index);
  4990.        
  4991.     if(clk==0)
  4992.     {
  4993.         removearmos(x,y);
  4994.     }
  4995.    
  4996.     if(stunclk==0 && clk>96)
  4997.         misc=1;
  4998.    
  4999.     if(!watch)
  5000.         floater_walk(misc?rate:0,      hrate, dstep/100.0,dstep/1000.0, 10,  80, 16);
  5001.    
  5002.     if(get_bit(quest_rules,qr_ENEMIESZAXIS) && !(tmpscr->flags7&fSIDEVIEW))
  5003.     {
  5004.         z=int(step*1.1/(fix)((dstep/1000.0)*1.1));
  5005.     }
  5006.    
  5007.     if(watch && get_bit(quest_rules,qr_PEAHATCLOCKVULN))
  5008.         superman=0;
  5009.     else
  5010.         superman=(movestatus && !get_bit(quest_rules,qr_ENEMIESZAXIS)) ? 1 : 0;
  5011.     stunclk=0;
  5012.    
  5013.     if(x<16) dir=right; //this is ugly, but so is moving or creating these guys with scripts.
  5014.    
  5015.     return enemy::animate(index);
  5016. }
  5017.  
  5018. void ePeahat::drawshadow(BITMAP *dest, bool translucent)
  5019. {
  5020.     int tempy=yofs;
  5021.     flip = 0;
  5022.     shadowtile = wpnsbuf[iwShadow].tile+posframe;
  5023.    
  5024.     if(!get_bit(quest_rules,qr_ENEMIESZAXIS))
  5025.     {
  5026.         yofs+=8;
  5027.         yofs+=int(step/(dstep/1000.0));
  5028.     }
  5029.    
  5030.     enemy::drawshadow(dest,translucent);
  5031.     yofs=tempy;
  5032. }
  5033.  
  5034. void ePeahat::draw(BITMAP *dest)
  5035. {
  5036.     update_enemy_frame();
  5037.     enemy::draw(dest);
  5038. }
  5039.  
  5040. int ePeahat::takehit(weapon *w)
  5041. {
  5042.     int wpnId = w->id;
  5043.     int enemyHitWeapon = w->parentitem;
  5044.    
  5045.     if(dying || clk<0 || hclk>0)
  5046.         return 0;
  5047.        
  5048.     if(superman && !(wpnId==wSBomb)            // vulnerable to super bombs
  5049.             // fire boomerang, for nailing peahats
  5050.             && !(wpnId==wBrang && (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_brang))>0))
  5051.         return 0;
  5052.        
  5053.     // Time for a kludge...
  5054.     int s = superman;
  5055.     superman = 0;
  5056.     int ret = enemy::takehit(w);
  5057.     superman = s;
  5058.    
  5059.     // Anyway...
  5060.     if(stunclk == 160)
  5061.     {
  5062.         clk2=0;
  5063.         movestatus=0;
  5064.         misc=0;
  5065.         clk=0;
  5066.         step=0;
  5067.     }
  5068.    
  5069.     return ret;
  5070. }
  5071.  
  5072. // auomatically kill off enemy (for rooms with ringleaders)
  5073. void ePeahat::kickbucket()
  5074. {
  5075.     hp=-1000;                                               // don't call death_sfx()
  5076. }
  5077.  
  5078. eLeever::eLeever(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  5079. {
  5080. //  if(d->misc1==0) { misc=-1; clk-=16; } //Line of Sight leevers
  5081.     if(dmisc1==0)
  5082.     {
  5083.         misc=-1;    //Line of Sight leevers
  5084.         clk-=16;
  5085.     }
  5086.    
  5087.     //nets+1460;
  5088.     temprule=(get_bit(quest_rules,qr_NEWENEMYTILES)) != 0;
  5089. }
  5090.  
  5091. bool eLeever::animate(int index)
  5092. {
  5093.     if(dying)
  5094.         return Dead(index);
  5095.        
  5096.     if(clk==0)
  5097.     {
  5098.         removearmos(x,y);
  5099.     }
  5100.    
  5101.     if(clk>=0 && !slide())
  5102.     {
  5103. //    switch(d->misc1)
  5104.         switch(dmisc1)
  5105.         {
  5106.         case 0:      //line of sight
  5107.         case 2:
  5108.             switch(misc) //is this leever active
  5109.             {
  5110.             case -1:  //submerged
  5111.             {
  5112.                 if((dmisc1==2)&&(rand()&255))
  5113.                 {
  5114.                     break;
  5115.                 }
  5116.                
  5117.                 int active=0;
  5118.                
  5119.                 for(int i=0; i<guys.Count(); i++)
  5120.                 {
  5121.                     if(guys.spr(i)->id==id && (((enemy*)guys.spr(i))->misc>=0))
  5122.                     {
  5123.                         ++active;
  5124.                     }
  5125.                 }
  5126.                
  5127.                 if(active<((dmisc1==2)?1:2))
  5128.                 {
  5129.                     misc=0; //activate this one
  5130.                 }
  5131.             }
  5132.             break;
  5133.            
  5134.             case 0:
  5135.             {
  5136.                 int s=0;
  5137.                
  5138.                 for(int i=0; i<guys.Count(); i++)
  5139.                 {
  5140.                     if(guys.spr(i)->id==id && ((enemy*)guys.spr(i))->misc==1)
  5141.                     {
  5142.                         ++s;
  5143.                     }
  5144.                 }
  5145.                
  5146.                 if(s>0)
  5147.                 {
  5148.                     break;
  5149.                 }
  5150.                
  5151.                 int d2=rand()&1;
  5152.                
  5153.                 if(LinkDir()>=left)
  5154.                 {
  5155.                     d2+=2;
  5156.                 }
  5157.                
  5158.                 if(canplace(d2) || canplace(d2^1))
  5159.                 {
  5160.                     misc=1;
  5161.                     clk2=0;
  5162.                     clk=0;
  5163.                 }
  5164.             }
  5165.             break;
  5166.            
  5167.             case 1:
  5168.                 if(++clk2>16) misc=2;
  5169.                
  5170.                 break;
  5171.                
  5172.             case 2:
  5173.                 if(++clk2>24) misc=3;
  5174.                
  5175.                 break;
  5176.                
  5177. //        case 3: if(stunclk) break; if(scored) dir^=1; if(!canmove(dir)) misc=4; else move((fix)(d->step/100.0)); break;
  5178.             case 3:
  5179.                 if(stunclk) break;
  5180.                
  5181.                 if(scored) dir^=1;
  5182.                
  5183.                 if(!canmove(dir)) misc=4;
  5184.                 else move((fix)(dstep/100.0));
  5185.                
  5186.                 break;
  5187.                
  5188.             case 4:
  5189.                 if(--clk2==16)
  5190.                 {
  5191.                     misc=5;
  5192.                     clk=8;
  5193.                 }
  5194.                
  5195.                 break;
  5196.                
  5197.             case 5:
  5198.                 if(--clk2==0)  misc=((dmisc1==2)?-1:0);
  5199.                
  5200.                 break;
  5201.             }                                                       // switch(misc)
  5202.            
  5203.             break;
  5204.            
  5205.         default:  //random
  5206. //      step=d->misc3/100.0;
  5207.             step=dmisc3/100.0;
  5208.             ++clk2;
  5209.            
  5210.             if(clk2<32)    misc=1;
  5211.             else if(clk2<48)    misc=2;
  5212.             else if(clk2<300)
  5213.             {
  5214.                 /*if(misc==2 && (int)(dmisc3*0.48)%8)
  5215.                 {
  5216.                   fix_coords();
  5217.                 }*/
  5218.                 misc=3;
  5219.                 step = dstep/100.0;
  5220.             }
  5221.             else if(clk2<316)   misc=2;
  5222.             else if(clk2<412)   misc=1;
  5223.             else if(clk2<540)
  5224.             {
  5225.                 misc=0;
  5226.                 step=0;
  5227.             }
  5228.             else clk2=0;
  5229.            
  5230.             if(clk2==48) clk=0;
  5231.            
  5232. //      variable_walk(d->rate, d->homing, 0);
  5233.             variable_walk(rate, homing, 0);
  5234.         }                                                         // switch(dmisc1)
  5235.     }
  5236.    
  5237.     hxofs=(misc>=2)?0:1000;
  5238.     return enemy::animate(index);
  5239. }
  5240.  
  5241. bool eLeever::canplace(int d2)
  5242. {
  5243.     int nx=LinkX();
  5244.     int ny=LinkY();
  5245.    
  5246.     if(d2<left) ny&=0xF0;
  5247.     else       nx&=0xF0;
  5248.    
  5249.     switch(d2)
  5250.     {
  5251. //    case up:    ny-=((d->misc1==0)?32:48); break;
  5252. //    case down:  ny+=((d->misc1==0)?32:48); if(ny-LinkY()<32) ny+=((d->misc1==0)?16:0); break;
  5253. //    case left:  nx-=((d->misc1==0)?32:48); break;
  5254. //    case right: nx+=((d->misc1==0)?32:48); if(nx-LinkX()<32) nx+=((d->misc1==0)?16:0); break;
  5255.     case up:
  5256.         ny-=((dmisc1==0||dmisc1==2)?32:48);
  5257.         break;
  5258.        
  5259.     case down:
  5260.         ny+=((dmisc1==0||dmisc1==2)?32:48);
  5261.        
  5262.         if(ny-LinkY()<32) ny+=((dmisc1==0||dmisc1==2)?16:0);
  5263.        
  5264.         break;
  5265.        
  5266.     case left:
  5267.         nx-=((dmisc1==0||dmisc1==2)?32:48);
  5268.         break;
  5269.        
  5270.     case right:
  5271.         nx+=((dmisc1==0||dmisc1==2)?32:48);
  5272.        
  5273.         if(nx-LinkX()<32) nx+=((dmisc1==0||dmisc1==2)?16:0);
  5274.        
  5275.         break;
  5276.     }
  5277.    
  5278.     if(m_walkflag(nx,ny,spw_halfstep)||m_walkflag(nx,ny-8,spw_halfstep))                         /*none*/
  5279.         return false;
  5280.        
  5281.     if(d2>=left)
  5282.         if(m_walkflag(LinkX(),LinkY(),spw_halfstep)||m_walkflag(LinkX(),LinkY()-8,spw_halfstep))                         /*none*/
  5283.             return false;
  5284.            
  5285.     x=nx;
  5286.     y=ny;
  5287.     dir=d2^1;
  5288.     return true;
  5289. }
  5290.  
  5291. void eLeever::draw(BITMAP *dest)
  5292. {
  5293. //  cs=d->cset;
  5294.     cs=dcset;
  5295.     update_enemy_frame();
  5296.    
  5297.     switch(misc)
  5298.     {
  5299.     case -1:
  5300.     case 0:
  5301.         return;
  5302.     }
  5303.    
  5304.     enemy::draw(dest);
  5305. }
  5306.  
  5307. eWallM::eWallM(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  5308. {
  5309.     haslink=false;
  5310.     //nets+1000;
  5311. }
  5312.  
  5313. bool eWallM::animate(int index)
  5314. {
  5315.     if(dying)
  5316.         return Dead(index);
  5317.        
  5318.     if(clk==0)
  5319.     {
  5320.         removearmos(x,y);
  5321.     }
  5322.    
  5323.     hxofs=1000;
  5324.    
  5325.     if(misc==0) //inside wall, ready to spawn?
  5326.     {
  5327.         if(frame-wallm_load_clk>80 && clk>=0)
  5328.         {
  5329.             int wall=link_on_wall();
  5330.             int wallm_cnt=0;
  5331.            
  5332.             for(int i=0; i<guys.Count(); i++)
  5333.                 if(((enemy*)guys.spr(i))->family==eeWALLM)
  5334.                 {
  5335.                     register int m=((enemy*)guys.spr(i))->misc;
  5336.                    
  5337.                     if(m && ((enemy*)guys.spr(i))->clk3==(wall^1))
  5338.                     {
  5339.                         ++wallm_cnt;
  5340.                     }
  5341.                 }
  5342.                
  5343.             if(wall>0)
  5344.             {
  5345.                 --wall;
  5346.                 misc=1; //emerging from the wall?
  5347.                 clk2=0;
  5348.                 clk3=wall^1;
  5349.                 wallm_load_clk=frame;
  5350.                
  5351.                 if(wall<=down)
  5352.                 {
  5353.                     if(LinkDir()==left)
  5354.                         dir=right;
  5355.                     else
  5356.                         dir=left;
  5357.                 }
  5358.                 else
  5359.                 {
  5360.                     if(LinkDir()==up)
  5361.                         dir=down;
  5362.                     else
  5363.                         dir=up;
  5364.                 }
  5365.                
  5366.                 switch(wall)
  5367.                 {
  5368.                 case up:
  5369.                     y=0;
  5370.                     break;
  5371.                    
  5372.                 case down:
  5373.                     y=160;
  5374.                     break;
  5375.                    
  5376.                 case left:
  5377.                     x=0;
  5378.                     break;
  5379.                    
  5380.                 case right:
  5381.                     x=240;
  5382.                     break;
  5383.                 }
  5384.                
  5385.                 switch(dir)
  5386.                 {
  5387.                 case up:
  5388.                     y=LinkY()+48-(wallm_cnt&1)*12;
  5389.                     flip=wall&1;
  5390.                     break;
  5391.                    
  5392.                 case down:
  5393.                     y=LinkY()-48+(wallm_cnt&1)*12;
  5394.                     flip=((wall&1)^1)+2;
  5395.                     break;
  5396.                    
  5397.                 case left:
  5398.                     x=LinkX()+48-(wallm_cnt&1)*12;
  5399.                     flip=(wall==up?2:0)+1;
  5400.                     break;
  5401.                    
  5402.                 case right:
  5403.                     x=LinkX()-48+(wallm_cnt&1)*12;
  5404.                     flip=(wall==up?2:0);
  5405.                     break;
  5406.                 }
  5407.             }
  5408.         }
  5409.     }
  5410.     else
  5411.         wallm_crawl();
  5412.        
  5413.     return enemy::animate(index);
  5414. }
  5415.  
  5416. void eWallM::wallm_crawl()
  5417. {
  5418.     bool w=watch;
  5419.     hxofs=0;
  5420.    
  5421.     if(slide())
  5422.     {
  5423.         return;
  5424.     }
  5425.    
  5426.     //  if(dying || watch || (!haslink && stunclk))
  5427.     if(dying || (!haslink && stunclk))
  5428.     {
  5429.         return;
  5430.     }
  5431.    
  5432.     watch=false;
  5433.     ++clk2;
  5434.     // Misc1: slightly different movement
  5435.     misc=(clk2/(dmisc1==1?40:int((40.0/dstep)*40)))+1;
  5436.    
  5437.     if(w&&misc>=3&&misc<=5)
  5438.     {
  5439.         --clk2;
  5440.     }
  5441.    
  5442.     switch(misc)
  5443.     {
  5444.     case 1:
  5445.     case 2:
  5446.         zc_swap(dir,clk3);
  5447.         move(step);
  5448.         zc_swap(dir,clk3);
  5449.         break;
  5450.        
  5451.     case 3:
  5452.     case 4:
  5453.     case 5:
  5454.         if(w)
  5455.         {
  5456.             watch=w;
  5457.             return;
  5458.         }
  5459.        
  5460.         move(step);
  5461.         break;
  5462.        
  5463.     case 6:
  5464.     case 7:
  5465.         zc_swap(dir,clk3);
  5466.         dir^=1;
  5467.         move(step);
  5468.         dir^=1;
  5469.         zc_swap(dir,clk3);
  5470.         break;
  5471.        
  5472.     default:
  5473.         misc=0;
  5474.         break;
  5475.     }
  5476.    
  5477.     watch=w;
  5478. }
  5479.  
  5480. void eWallM::grablink()
  5481. {
  5482.     haslink=true;
  5483.     superman=1;
  5484. }
  5485.  
  5486. void eWallM::draw(BITMAP *dest)
  5487. {
  5488.     dummy_bool[1]=haslink;
  5489.     update_enemy_frame();
  5490.    
  5491.     if(misc>0)
  5492.     {
  5493.         masked_draw(dest,16,playing_field_offset+16,224,144);
  5494.     }
  5495.    
  5496.     //    enemy::draw(dest);
  5497.     //    tile = clk&8 ? 128:129;
  5498. }
  5499.  
  5500. eTrap::eTrap(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  5501. {
  5502.     ox=x;                                                     //original x
  5503.     oy=y;                                                     //original y
  5504.    
  5505.     if(get_bit(quest_rules,qr_TRAPPOSFIX))
  5506.     {
  5507.         yofs = playing_field_offset;
  5508.     }
  5509.    
  5510.     mainguy=false;
  5511.     count_enemy=false;
  5512.     //nets+420;
  5513.     dummy_int[1]=0;
  5514. }
  5515.  
  5516. bool eTrap::animate(int index)
  5517. {
  5518.     if(clk<0)
  5519.         return enemy::animate(index);
  5520.        
  5521.     if(clk==0)
  5522.     {
  5523.         removearmos(x,y);
  5524.     }
  5525.    
  5526.     if(misc==0)                                               // waiting
  5527.     {
  5528.         ox = x;
  5529.         oy = y;
  5530.         double ddir=atan2(double(y-(Link.y)),double(Link.x-x));
  5531.        
  5532.         if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4)))
  5533.         {
  5534.             dir=down;
  5535.         }
  5536.         else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4)))
  5537.         {
  5538.             dir=right;
  5539.         }
  5540.         else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/4)))
  5541.         {
  5542.             dir=up;
  5543.         }
  5544.         else
  5545.         {
  5546.             dir=left;
  5547.         }
  5548.        
  5549.         int d2=lined_up(15,true);
  5550.        
  5551.         if(((d2<left || d2 > right) && (dmisc1==1)) ||
  5552.                 ((d2>down) && (dmisc1==2)) ||
  5553.                 ((d2>right) && (!dmisc1)) ||
  5554.                 ((d2<l_up) && (dmisc1==4)) ||
  5555.                 ((d2!=r_up) && (d2!=l_down) && (dmisc1==6)) ||
  5556.                 ((d2!=l_up) && (d2!=r_down) && (dmisc1==8)))
  5557.         {
  5558.             d2=-1;
  5559.         }
  5560.        
  5561.         if(d2!=-1 && trapmove(d2))
  5562.         {
  5563.             dir=d2;
  5564.             misc=1;
  5565.             clk2=(dir==down)?3:0;
  5566.         }
  5567.     }
  5568.    
  5569.     if(misc==1)                                               // charging
  5570.     {
  5571.         clk2=(clk2+1)&3;
  5572.         step=(clk2==3)?1:2;
  5573.        
  5574.         if(!trapmove(dir) || clip())
  5575.         {
  5576.             misc=2;
  5577.            
  5578.             if(dir<l_up)
  5579.             {
  5580.                 dir=dir^1;
  5581.             }
  5582.             else
  5583.             {
  5584.                 dir=dir^3;
  5585.             }
  5586.         }
  5587.         else
  5588.         {
  5589.             sprite::move(step);
  5590.         }
  5591.     }
  5592.    
  5593.     if(misc==2)                                               // retreating
  5594.     {
  5595.         step=(++clk2&1)?1:0;
  5596.        
  5597.         switch(dir)
  5598.         {
  5599.         case up:
  5600.             if(int(y)<=oy) goto trap_rest;
  5601.             else sprite::move(step);
  5602.            
  5603.             break;
  5604.            
  5605.         case left:
  5606.             if(int(x)<=ox) goto trap_rest;
  5607.             else sprite::move(step);
  5608.            
  5609.             break;
  5610.            
  5611.         case down:
  5612.             if(int(y)>=oy) goto trap_rest;
  5613.             else sprite::move(step);
  5614.            
  5615.             break;
  5616.            
  5617.         case right:
  5618.             if(int(x)>=ox) goto trap_rest;
  5619.             else sprite::move(step);
  5620.            
  5621.             break;
  5622.            
  5623.         case l_up:
  5624.             if(int(x)<=ox && int(y)<=oy) goto trap_rest;
  5625.             else sprite::move(step);
  5626.            
  5627.             break;
  5628.            
  5629.         case r_up:
  5630.             if(int(x)>=ox && int(y)<=oy) goto trap_rest;
  5631.             else sprite::move(step);
  5632.            
  5633.             break;
  5634.            
  5635.         case l_down:
  5636.             if(int(x)<=ox && int(y)>=oy) goto trap_rest;
  5637.             else sprite::move(step);
  5638.            
  5639.             break;
  5640.            
  5641.         case r_down:
  5642.             if(int(x)>=ox && int(y)>=oy) goto trap_rest;
  5643.             else sprite::move(step);
  5644.            
  5645.             break;
  5646. trap_rest:
  5647.             {
  5648.                 x=ox;
  5649.                 y=oy;
  5650.                 misc=0;
  5651.             }
  5652.         }
  5653.     }
  5654.    
  5655.     return enemy::animate(index);
  5656. }
  5657.  
  5658. bool eTrap::trapmove(int ndir)
  5659. {
  5660.     if(get_bit(quest_rules,qr_MEANTRAPS))
  5661.     {
  5662.         if(tmpscr->flags2&fFLOATTRAPS)
  5663.             return canmove(ndir,(fix)1,spw_floater, 0, 0, 15, 15);
  5664.            
  5665.         return canmove(ndir,(fix)1,spw_water, 0, 0, 15, 15);
  5666.     }
  5667.    
  5668.     if(oy==80 && !(ndir==left || ndir == right))
  5669.         return false;
  5670.        
  5671.     if(ox==128 && !(ndir==up || ndir==down))
  5672.         return false;
  5673.        
  5674.     if(oy<80 && ndir==up)
  5675.         return false;
  5676.        
  5677.     if(oy>80 && ndir==down)
  5678.         return false;
  5679.        
  5680.     if(ox<128 && ndir==left)
  5681.         return false;
  5682.        
  5683.     if(ox>128 && ndir==right)
  5684.         return false;
  5685.        
  5686.     if(ox<128 && oy<80 && ndir==l_up)
  5687.         return false;
  5688.        
  5689.     if(ox<128 && oy>80 && ndir==l_down)
  5690.         return false;
  5691.        
  5692.     if(ox>128 && oy<80 && ndir==r_up)
  5693.         return false;
  5694.        
  5695.     if(ox>128 && oy>80 && ndir==r_down)
  5696.         return false;
  5697.        
  5698.     return true;
  5699. }
  5700.  
  5701. bool eTrap::clip()
  5702. {
  5703.     if(get_bit(quest_rules,qr_MEANPLACEDTRAPS))
  5704.     {
  5705.         switch(dir)
  5706.         {
  5707.         case up:
  5708.             if(y<=0)           return true;
  5709.            
  5710.             break;
  5711.            
  5712.         case down:
  5713.             if(y>=160)         return true;
  5714.            
  5715.             break;
  5716.            
  5717.         case left:
  5718.             if(x<=0)           return true;
  5719.            
  5720.             break;
  5721.            
  5722.         case right:
  5723.             if(x>=240)         return true;
  5724.            
  5725.             break;
  5726.            
  5727.         case l_up:
  5728.             if(y<=0||x<=0)     return true;
  5729.            
  5730.             break;
  5731.            
  5732.         case l_down:
  5733.             if(y>=160||x<=0)   return true;
  5734.            
  5735.             break;
  5736.            
  5737.         case r_up:
  5738.             if(y<=0||x>=240)   return true;
  5739.            
  5740.             break;
  5741.            
  5742.         case r_down:
  5743.             if(y>=160||x>=240) return true;
  5744.            
  5745.             break;
  5746.         }
  5747.        
  5748.         return false;
  5749.     }
  5750.     else
  5751.     {
  5752.         switch(dir)
  5753.         {
  5754.         case up:
  5755.             if(oy>80 && y<=86) return true;
  5756.            
  5757.             break;
  5758.            
  5759.         case down:
  5760.             if(oy<80 && y>=80) return true;
  5761.            
  5762.             break;
  5763.            
  5764.         case left:
  5765.             if(ox>128 && x<=124) return true;
  5766.            
  5767.             break;
  5768.            
  5769.         case right:
  5770.             if(ox<120 && x>=116) return true;
  5771.            
  5772.             break;
  5773.            
  5774.         case l_up:
  5775.             if(oy>80 && y<=86 && ox>128 && x<=124) return true;
  5776.            
  5777.             break;
  5778.            
  5779.         case l_down:
  5780.             if(oy<80 && y>=80 && ox>128 && x<=124) return true;
  5781.            
  5782.             break;
  5783.            
  5784.         case r_up:
  5785.             if(oy>80 && y<=86 && ox<120 && x>=116) return true;
  5786.            
  5787.             break;
  5788.            
  5789.         case r_down:
  5790.             if(oy<80 && y>=80 && ox<120 && x>=116) return true;
  5791.            
  5792.             break;
  5793.         }
  5794.        
  5795.         return false;
  5796.     }
  5797. }
  5798.  
  5799. void eTrap::draw(BITMAP *dest)
  5800. {
  5801.     update_enemy_frame();
  5802.     enemy::draw(dest);
  5803. }
  5804.  
  5805. int eTrap::takehit(weapon*)
  5806. {
  5807.     return 0;
  5808. }
  5809.  
  5810. eTrap2::eTrap2(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  5811. {
  5812.     lasthit=-1;
  5813.     lasthitclk=0;
  5814.     mainguy=false;
  5815.     count_enemy=false;
  5816.     step=2;
  5817.    
  5818.     if(dmisc1==1 || (dmisc1==0 && rand()&2))
  5819.     {
  5820.         dir=(x<=112)?right:left;
  5821.     }
  5822.     else
  5823.     {
  5824.         dir=(y<=72)?down:up;
  5825.     }
  5826.    
  5827.     if(get_bit(quest_rules,qr_TRAPPOSFIX))
  5828.     {
  5829.         yofs = playing_field_offset;
  5830.     }
  5831.    
  5832.     //nets+((id==eTRAP_LR)?540:520);
  5833.     dummy_int[1]=0;
  5834. }
  5835.  
  5836. bool eTrap2::animate(int index)
  5837. {
  5838.     if(clk<0)
  5839.         return enemy::animate(index);
  5840.        
  5841.     if(clk==0)
  5842.     {
  5843.         removearmos(x,y);
  5844.     }
  5845.    
  5846.     if(!get_bit(quest_rules,qr_PHANTOMPLACEDTRAPS))
  5847.     {
  5848.         if(lasthitclk>0)
  5849.         {
  5850.             --lasthitclk;
  5851.         }
  5852.         else
  5853.         {
  5854.             lasthit=-1;
  5855.         }
  5856.        
  5857.         bool hitenemy=false;
  5858.        
  5859.         for(int j=0; j<guys.Count(); j++)
  5860.         {
  5861.             if((j!=index) && (lasthit!=j))
  5862.             {
  5863.                 if(hit(guys.spr(j)))
  5864.                 {
  5865.                     lasthit=j;
  5866.                     lasthitclk=10;
  5867.                     hitenemy=true;
  5868.                     guys.spr(j)->lasthit=index;
  5869.                     guys.spr(j)->lasthitclk=10;
  5870. //          guys.spr(j)->dir=guys.spr(j)->dir^1;
  5871.                 }
  5872.             }
  5873.         }
  5874.        
  5875.         if(!trapmove(dir) || clip() || hitenemy)
  5876.         {
  5877.             if(!trapmove(dir) || clip())
  5878.             {
  5879.                 lasthit=-1;
  5880.                 lasthitclk=0;
  5881.             }
  5882.            
  5883.             if(get_bit(quest_rules,qr_MORESOUNDS))
  5884.                 Backend::sfx->play(WAV_ZN1TAP,int(x));
  5885.                
  5886.             dir=dir^1;
  5887.         }
  5888.        
  5889.         sprite::move(step);
  5890.     }
  5891.     else
  5892.     {
  5893.         if(!trapmove(dir) || clip())
  5894.         {
  5895.             if(get_bit(quest_rules,qr_MORESOUNDS))
  5896.                 Backend::sfx->play(WAV_ZN1TAP,int(x));
  5897.                
  5898.             dir=dir^1;
  5899.         }
  5900.        
  5901.         sprite::move(step);
  5902.     }
  5903.    
  5904.     return enemy::animate(index);
  5905. }
  5906.  
  5907. bool eTrap2::trapmove(int ndir)
  5908. {
  5909.     if(tmpscr->flags2&fFLOATTRAPS)
  5910.         return canmove(ndir,(fix)1,spw_floater, 0, 0, 15, 15);
  5911.        
  5912.     return canmove(ndir,(fix)1,spw_water, 0, 0, 15, 15);
  5913. }
  5914.  
  5915. bool eTrap2::clip()
  5916. {
  5917.     switch(dir)
  5918.     {
  5919.     case up:
  5920.         if(y<=0) return true;
  5921.        
  5922.         break;
  5923.        
  5924.     case down:
  5925.         if(y>=160) return true;
  5926.        
  5927.         break;
  5928.        
  5929.     case left:
  5930.         if(x<=0) return true;
  5931.        
  5932.         break;
  5933.        
  5934.     case right:
  5935.         if(x>=240) return true;
  5936.        
  5937.         break;
  5938.     }
  5939.    
  5940.     return false;
  5941. }
  5942.  
  5943. void eTrap2::draw(BITMAP *dest)
  5944. {
  5945.     update_enemy_frame();
  5946.     enemy::draw(dest);
  5947. }
  5948.  
  5949. int eTrap2::takehit(weapon*)
  5950. {
  5951.     return 0;
  5952. }
  5953.  
  5954. eRock::eRock(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  5955. {
  5956.     //do not show "enemy appering" anim -DD
  5957.     clk=0;
  5958.     mainguy=false;
  5959.     clk2=-14;
  5960.     hxofs=hyofs=-2;
  5961.     hxsz=hysz=20;
  5962.     //nets+1640;
  5963. }
  5964.  
  5965. bool eRock::animate(int index)
  5966. {
  5967.     if(dying)
  5968.         return Dead(index);
  5969.        
  5970.     if(clk==0)
  5971.     {
  5972.         removearmos(x,y);
  5973.     }
  5974.    
  5975.     if(++clk2==0)                                             // start it
  5976.     {
  5977.         x=rand()&0xF0;
  5978.         y=0;
  5979.         clk3=0;
  5980.         clk2=rand()&15;
  5981.     }
  5982.    
  5983.     if(clk2>16)                                               // move it
  5984.     {
  5985.         if(clk3<=0)                                             // start bounce
  5986.         {
  5987.             dir=rand()&1;
  5988.            
  5989.             if(x<32)  dir=1;
  5990.            
  5991.             if(x>208) dir=0;
  5992.         }
  5993.        
  5994.         if(clk3<13+16)
  5995.         {
  5996.             x += dir ? 1 : -1;                                    //right, left
  5997.             dummy_int[1]=dir;
  5998.            
  5999.             if(clk3<2)
  6000.             {
  6001.                 y-=2;    //up
  6002.                 dummy_int[2]=(dummy_int[1]==1)?r_up:l_up;
  6003.             }
  6004.             else if(clk3<5)