Advertisement
ZoriaRPG

guys.cpp 12-June-2017

Jun 12th, 2017
230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 357.17 KB | None | 0 0
  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)
  6005.             {
  6006.                 y--;    //up
  6007.                 dummy_int[2]=(dummy_int[1]==1)?r_up:l_up;
  6008.             }
  6009.             else if(clk3<8)
  6010.             {
  6011.                 dummy_int[2]=(dummy_int[1]==1)?right:left;
  6012.             }
  6013.             else if(clk3<11)
  6014.             {
  6015.                 y++;   //down
  6016.                 dummy_int[2]=(dummy_int[1]==1)?r_down:l_down;
  6017.             }
  6018.             else
  6019.             {
  6020.                 y+=2; //down
  6021.                 dummy_int[2]=(dummy_int[1]==1)?r_down:l_down;
  6022.             }
  6023.            
  6024.             ++clk3;
  6025.         }
  6026.         else if(y<176)
  6027.             clk3=0;                                               // next bounce
  6028.         else
  6029.             clk2 = -(rand()&63);                                  // back to top
  6030.     }
  6031.    
  6032.     return enemy::animate(index);
  6033. }
  6034.  
  6035. void eRock::drawshadow(BITMAP *dest, bool translucent)
  6036. {
  6037.     if(clk2>=0)
  6038.     {
  6039.         int tempy=yofs;
  6040.         flip = 0;
  6041.         int fdiv = frate/4;
  6042.         int efrate = fdiv == 0 ? 0 : clk/fdiv;
  6043.         int f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
  6044.                efrate:((clk>=(frate>>1))?1:0);
  6045.         shadowtile = wpnsbuf[iwShadow].tile+f2;
  6046.        
  6047.         yofs+=8;
  6048.         yofs+=zc_max(0,zc_min(29-clk3,clk3));
  6049.         enemy::drawshadow(dest, translucent);
  6050.         yofs=tempy;
  6051.     }
  6052. }
  6053.  
  6054. void eRock::draw(BITMAP *dest)
  6055. {
  6056.     if(clk2>=0)
  6057.     {
  6058.         int tempdir=dir;
  6059.         dir=dummy_int[2];
  6060.         update_enemy_frame();
  6061.         enemy::draw(dest);
  6062.         dir=tempdir;
  6063.     }
  6064. }
  6065.  
  6066. int eRock::takehit(weapon*)
  6067. {
  6068.     return 0;
  6069. }
  6070.  
  6071. eBoulder::eBoulder(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  6072. {
  6073.     clk=0;
  6074.     mainguy=false;
  6075.     clk2=-14;
  6076.     hxofs=hyofs=-10;
  6077.     hxsz=hysz=36;
  6078.     hzsz=16; //can't be jumped
  6079.     //nets+1680;
  6080. }
  6081.  
  6082. bool eBoulder::animate(int index)
  6083. {
  6084.     if(dying)
  6085.         return Dead(index);
  6086.        
  6087.     if(clk==0)
  6088.     {
  6089.         removearmos(x,y);
  6090.     }
  6091.    
  6092.     fix *vert;
  6093.     vert = get_bit(quest_rules,qr_ENEMIESZAXIS) ? &z : &y;
  6094.    
  6095.     if(++clk2==0)                                             // start it
  6096.     {
  6097.         x=rand()&0xF0;
  6098.         y=-32;
  6099.         clk3=0;
  6100.         clk2=rand()&15;
  6101.     }
  6102.    
  6103.     if(clk2>16)                                               // move it
  6104.     {
  6105.         if(clk3<=0)                                             // start bounce
  6106.         {
  6107.             dir=rand()&1;
  6108.            
  6109.             if(x<32)  dir=1;
  6110.            
  6111.             if(x>208) dir=0;
  6112.         }
  6113.        
  6114.         if(clk3<13+16)
  6115.         {
  6116.             x += dir ? 1 : -1;                                    //right, left
  6117.             dummy_int[1]=dir;
  6118.            
  6119.             if(clk3<2)
  6120.             {
  6121.                 y-=2;    //up
  6122.                 dummy_int[2]=(dummy_int[1]==1)?r_up:l_up;
  6123.             }
  6124.             else if(clk3<5)
  6125.             {
  6126.                 y--;    //up
  6127.                 dummy_int[2]=(dummy_int[1]==1)?r_up:l_up;
  6128.             }
  6129.             else if(clk3<8)
  6130.             {
  6131.                 dummy_int[2]=(dummy_int[1]==1)?right:left;
  6132.             }
  6133.             else if(clk3<11)
  6134.             {
  6135.                 y++;     //down
  6136.                 dummy_int[2]=(dummy_int[1]==1)?r_down:l_down;
  6137.             }
  6138.             else
  6139.             {
  6140.                 y+=2; //down
  6141.                 dummy_int[2]=(dummy_int[1]==1)?r_down:l_down;
  6142.             }
  6143.            
  6144.             ++clk3;
  6145.         }
  6146.         else if(y<176)
  6147.             clk3=0;                                               // next bounce
  6148.         else
  6149.             clk2 = -(rand()&63);                                  // back to top
  6150.     }
  6151.    
  6152.     return enemy::animate(index);
  6153. }
  6154.  
  6155. void eBoulder::drawshadow(BITMAP *dest, bool translucent)
  6156. {
  6157.     if(clk2>=0)
  6158.     {
  6159.         int tempy=yofs;
  6160.         flip = 0;
  6161.         int f2=((clk<<2)/frate)<<1;
  6162.         shadowtile = wpnsbuf[iwLargeShadow].tile+f2;
  6163.         yofs+=zc_max(0,zc_min(29-clk3,clk3));
  6164.        
  6165.         yofs+=8;
  6166.         xofs-=8;
  6167.         enemy::drawshadow(dest, translucent);
  6168.         xofs+=16;
  6169.         ++shadowtile;
  6170.         enemy::drawshadow(dest, translucent);
  6171.         yofs+=16;
  6172.         shadowtile+=20;
  6173.         enemy::drawshadow(dest, translucent);
  6174.         xofs-=16;
  6175.         --shadowtile;
  6176.         enemy::drawshadow(dest, translucent);
  6177.         xofs+=8;
  6178.         yofs=tempy;
  6179.     }
  6180. }
  6181.  
  6182. void eBoulder::draw(BITMAP *dest)
  6183. {
  6184.     if(clk2>=0)
  6185.     {
  6186.         int tempdir=dir;
  6187.         dir=dummy_int[2];
  6188.         update_enemy_frame();
  6189.         dir=tempdir;
  6190.         xofs-=8;
  6191.         yofs-=8;
  6192.         drawblock(dest,15);
  6193.         xofs+=8;
  6194.         yofs+=8;
  6195.         //    enemy::draw(dest);
  6196.     }
  6197. }
  6198.  
  6199. int eBoulder::takehit(weapon*)
  6200. {
  6201.     return 0;
  6202. }
  6203.  
  6204. eProjectile::eProjectile(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk),
  6205.     minRange(get_bit(quest_rules, qr_BROKENSTATUES) ? 0 : Clk)
  6206. {
  6207.     /* fixing
  6208.       hp=1;
  6209.       */
  6210.     mainguy=false;
  6211.     count_enemy=false;
  6212.     hclk=clk;                                                 // the "no fire" range
  6213.     clk=0;
  6214.     clk3=96;
  6215.     timer=0;
  6216.    
  6217.     if(o_tile==0)
  6218.     {
  6219.         superman=1;
  6220.         hxofs=1000;
  6221.     }
  6222. }
  6223.  
  6224. bool eProjectile::animate(int index)
  6225. {
  6226.     if(clk==0)
  6227.     {
  6228.         removearmos(x,y);
  6229.     }
  6230.    
  6231.     double ddir=atan2(double(y-(Link.y)),double(Link.x-x));
  6232.    
  6233.     if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4)))
  6234.     {
  6235.         dir=down;
  6236.     }
  6237.     else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4)))
  6238.     {
  6239.         dir=right;
  6240.     }
  6241.     else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/4)))
  6242.     {
  6243.         dir=up;
  6244.     }
  6245.     else
  6246.     {
  6247.         dir=left;
  6248.     }
  6249.    
  6250.     if(++clk3>80)
  6251.     {
  6252.         if(dmisc1==9) // Breath type
  6253.         {
  6254.             if(timer==0)
  6255.             {
  6256.                 unsigned r=rand();
  6257.                
  6258.                 if(!(r&63))
  6259.                 {
  6260.                     timer=rand()%50+50;
  6261.                 }
  6262.             }
  6263.            
  6264.             if(timer>0)
  6265.             {
  6266.                 if(timer%4==0)
  6267.                 {
  6268.                     FireBreath(false);
  6269.                 }
  6270.                
  6271.                 if(--timer==0)
  6272.                 {
  6273.                     clk3=0;
  6274.                 }
  6275.             }
  6276.         }
  6277.        
  6278.         else // Not breath type
  6279.         {
  6280.             unsigned r=rand();
  6281.            
  6282.             if(!(r&63) && !LinkInRange(minRange))
  6283.             {
  6284.                 FireWeapon();
  6285.                
  6286.                 if(get_bit(quest_rules, qr_BROKENSTATUES)==0 &&
  6287.                   ((wpn==ewFireball || wpn==ewFireball2) || dmisc1==e1tNORMAL))
  6288.                 {
  6289.                     if(!((r>>7)&15))
  6290.                     {
  6291.                         x-=4;
  6292.                         FireWeapon();
  6293.                         x+=4;
  6294.                     }
  6295.                 }
  6296.                
  6297.                 clk3=0;
  6298.             }
  6299.         }
  6300.     }
  6301.    
  6302.     return enemy::animate(index);
  6303. }
  6304.  
  6305. void eProjectile::draw(BITMAP *dest)
  6306. {
  6307.     update_enemy_frame();
  6308.     enemy::draw(dest);
  6309. }
  6310.  
  6311. eTrigger::eTrigger(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  6312. {
  6313.     hxofs=1000;
  6314. }
  6315.  
  6316. void eTrigger::draw(BITMAP *dest)
  6317. {
  6318.     update_enemy_frame();
  6319.     enemy::draw(dest);
  6320. }
  6321.  
  6322. void eTrigger::death_sfx()
  6323. {
  6324.     //silent death
  6325. }
  6326.  
  6327. eNPC::eNPC(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  6328. {
  6329.     o_tile+=wpnsbuf[iwNPCs].tile;
  6330.     count_enemy=false;
  6331. }
  6332.  
  6333. bool eNPC::animate(int index)
  6334. {
  6335.     if(dying)
  6336.         return Dead(index);
  6337.        
  6338.     if(clk==0)
  6339.     {
  6340.         removearmos(x,y);
  6341.     }
  6342.    
  6343.     switch(dmisc2)
  6344.     {
  6345.     case 0:
  6346.     {
  6347.         double ddir=atan2(double(y-(Link.y)),double(Link.x-x));
  6348.        
  6349.         if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4)))
  6350.         {
  6351.             dir=down;
  6352.         }
  6353.        
  6354.         else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4)))
  6355.         {
  6356.             dir=right;
  6357.         }
  6358.         else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/8)))
  6359.         {
  6360.             dir=up;
  6361.         }
  6362.         else
  6363.         {
  6364.             dir=left;
  6365.         }
  6366.     }
  6367.     break;
  6368.    
  6369.     case 1:
  6370.         halting_walk(rate, homing, 0, hrate, 48);
  6371.        
  6372.         if(clk2==1 && (misc < dmisc1) && !(rand()&15))
  6373.         {
  6374.             newdir(rate, homing, 0);
  6375.             clk2=48;
  6376.             ++misc;
  6377.         }
  6378.        
  6379.         if(clk2==0)
  6380.             misc=0;
  6381.            
  6382.         break;
  6383.     }
  6384.    
  6385.     return enemy::animate(index);
  6386. }
  6387.  
  6388. void eNPC::draw(BITMAP *dest)
  6389. {
  6390.     update_enemy_frame();
  6391.     enemy::draw(dest);
  6392. }
  6393.  
  6394. int eNPC::takehit(weapon*)
  6395. {
  6396.     return 0;
  6397. }
  6398.  
  6399. eSpinTile::eSpinTile(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  6400. {
  6401.     if(clk>0)  // clk>0 when created by a Spinning Tile combo
  6402.     {
  6403.         o_tile=clk;
  6404.         cs=id>>12;
  6405.     }
  6406.    
  6407.     id=id&0xFFF;
  6408.     clk=0;
  6409.     step=0;
  6410.     mainguy=false;
  6411. }
  6412.  
  6413. void eSpinTile::facelink()
  6414. {
  6415.     if(Link.x-x==0)
  6416.     {
  6417.         if (Link.y + 8 < y)
  6418.             dir = up;
  6419.         else
  6420.             dir = down;
  6421.     }
  6422.     else
  6423.     {
  6424.         double ddir=atan2(double(y-(Link.y)),double(Link.x-x));
  6425.        
  6426.         if((ddir <= -5.0*PI/8.0) && (ddir > -7.0*PI/8.0))
  6427.         {
  6428.             dir=l_down;
  6429.         }
  6430.         else if ((ddir <= -3.0*PI / 8.0) && (ddir > -5.0*PI / 8.0))
  6431.         {
  6432.             dir=down;
  6433.         }
  6434.         else if ((ddir <= -1.0*PI / 8.0) && (ddir > -3.0*PI / 8.0))
  6435.         {
  6436.             dir=r_down;
  6437.         }
  6438.         else if ((ddir <= 1.0*PI / 8.0) && (ddir > -1.0*PI / 8.0))
  6439.         {
  6440.             dir=right;
  6441.         }
  6442.         else if ((ddir <= 3.0*PI / 8.0) && (ddir > 1.0*PI / 8.0))
  6443.         {
  6444.             dir=r_up;
  6445.         }
  6446.         else if ((ddir <= 5.0*PI / 8.0) && (ddir > 3.0*PI / 8.0))
  6447.         {
  6448.             dir=up;
  6449.         }
  6450.         else if ((ddir <= 7.0*PI / 8.0) && (ddir > 5.0*PI / 8.0))
  6451.         {
  6452.             dir=l_up;
  6453.         }
  6454.         else
  6455.         {
  6456.             dir=left;
  6457.         }
  6458.     }
  6459. }
  6460.  
  6461.  
  6462. bool eSpinTile::animate(int index)
  6463. {
  6464.     if(dying)
  6465.     {
  6466.         return Dead(index);
  6467.     }
  6468.    
  6469.     if(clk==0)
  6470.     {
  6471.         removearmos(x,y);
  6472.     }
  6473.    
  6474.     ++misc;
  6475.    
  6476.     if(misc==96)
  6477.     {
  6478.         facelink();
  6479.         double ddir=atan2(double((Link.y)-y),double(Link.x-x));
  6480.         angular=true;
  6481.         angle=ddir;
  6482.         step=(dstep/100.0);
  6483.     }
  6484.    
  6485.     if(y>186 || y<=-16 || x>272 || x<=-16)
  6486.         kickbucket();
  6487.        
  6488.     sprite::move(step);
  6489.     return enemy::animate(index);
  6490. }
  6491.  
  6492. void eSpinTile::draw(BITMAP *dest)
  6493. {
  6494.     update_enemy_frame();
  6495.     y-=(misc>>4);
  6496.     yofs+=2;
  6497.     enemy::draw(dest);
  6498.     yofs-=2;
  6499.     y+=(misc>>4);
  6500. }
  6501.  
  6502. void eSpinTile::drawshadow(BITMAP *dest, bool translucent)
  6503. {
  6504.     flip = 0;
  6505.     shadowtile = wpnsbuf[iwShadow].tile+(clk%4);
  6506.     yofs+=4;
  6507.     enemy::drawshadow(dest, translucent);
  6508.     yofs-=4;
  6509. }
  6510.  
  6511. eZora::eZora(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,0)
  6512. {
  6513.     //these are here to bypass compiler warnings about unused arguments
  6514.     Clk=Clk;
  6515.    
  6516.     mainguy=false;
  6517.     count_enemy=false;
  6518.     /*if((x>-17 && x<0) && iswater(tmpscr->data[(((int)y&0xF0)+((int)x>>4))]))
  6519.     {
  6520.       clk=1;
  6521.     }*/
  6522.     //nets+880;
  6523. }
  6524.  
  6525. void eZora::facelink()
  6526. {
  6527.     if(Link.x-x==0)
  6528.     {
  6529.         dir=(Link.y+8<y)?up:down;
  6530.     }
  6531.     else
  6532.     {
  6533.         double ddir=atan2(double(y-(Link.y)),double(Link.x-x));
  6534.        
  6535.         if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
  6536.         {
  6537.             dir=l_down;
  6538.         }
  6539.         else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
  6540.         {
  6541.             dir=down;
  6542.         }
  6543.         else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
  6544.         {
  6545.             dir=r_down;
  6546.         }
  6547.         else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
  6548.         {
  6549.             dir=right;
  6550.         }
  6551.         else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
  6552.         {
  6553.             dir=r_up;
  6554.         }
  6555.         else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
  6556.         {
  6557.             dir=up;
  6558.         }
  6559.         else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
  6560.         {
  6561.             dir=l_up;
  6562.         }
  6563.         else
  6564.         {
  6565.             dir=left;
  6566.         }
  6567.     }
  6568. }
  6569.  
  6570. bool eZora::animate(int index)
  6571. {
  6572.     if(dying)
  6573.         return Dead(index);
  6574.        
  6575.     if(clk==0)
  6576.     {
  6577.         removearmos(x,y);
  6578.     }
  6579.    
  6580.     if(watch)
  6581.     {
  6582.         ++clock_zoras[id];
  6583.         return true;
  6584.     }
  6585.    
  6586.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  6587.     {
  6588.         facelink();
  6589.     }
  6590.    
  6591.     switch(clk)
  6592.     {
  6593.     case 0:                                                 // reposition him
  6594.     {
  6595.         int t=0;
  6596.         int pos2=rand()%160 + 16;
  6597.         bool placed=false;
  6598.        
  6599.         while(!placed && t<160)
  6600.         {
  6601.             if(iswater(tmpscr->data[pos2]) && (pos2&15)>0 && (pos2&15)<15)
  6602.             {
  6603.                 x=(pos2&15)<<4;
  6604.                 y=pos2&0xF0;
  6605.                 hp=guysbuf[id&0xFFF].hp;                             // refill life each time
  6606.                 hxofs=1000;                                       // avoid hit detection
  6607.                 stunclk=0;
  6608.                 placed=true;
  6609.             }
  6610.            
  6611.             pos2+=19;
  6612.            
  6613.             if(pos2>=176)
  6614.                 pos2-=160;
  6615.                
  6616.             ++t;
  6617.         }
  6618.        
  6619.         if(!placed || whistleclk>=88)                         // can't place him, he's gone
  6620.             return true;
  6621.            
  6622.     }
  6623.     break;
  6624.    
  6625.     case 35:
  6626.         if(!get_bit(quest_rules,qr_NEWENEMYTILES))
  6627.         {
  6628.             dir=(Link.y+8<y)?up:down;
  6629.         }
  6630.        
  6631.         hxofs=0;
  6632.         break;
  6633.        
  6634. //    case 35+19: addEwpn(x,y,z,ewFireball,0,d->wdp,0); break;
  6635.     case 35+19:
  6636.         addEwpn(x,y,z,wpn,2,wdp,dir,getUID());
  6637.         Backend::sfx->play(wpnsfx(wpn),int(x));
  6638.         break;
  6639.        
  6640.     case 35+66:
  6641.         hxofs=1000;
  6642.         break;
  6643.        
  6644.     case 198:
  6645.         clk=-1;
  6646.         break;
  6647.     }
  6648.    
  6649.     return enemy::animate(index);
  6650. }
  6651.  
  6652. void eZora::draw(BITMAP *dest)
  6653. {
  6654.     if(clk<3)
  6655.         return;
  6656.        
  6657.     update_enemy_frame();
  6658.     enemy::draw(dest);
  6659. }
  6660.  
  6661. eStalfos::eStalfos(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  6662. {
  6663.     multishot= timer = fired = dashing = 0;
  6664.     haslink = false;
  6665.     dummy_bool[0]=false;
  6666.     shield= (flags&(inv_left | inv_right | inv_back |inv_front)) != 0;
  6667.    
  6668.     if(dmisc9==e9tARMOS && rand()&1)
  6669.     {
  6670.         step=(dmisc10)/100.0;
  6671.        
  6672.         if(anim==aARMOS4) o_tile+=20;
  6673.     }
  6674.    
  6675.     if(flags & guy_fadeflicker)
  6676.     {
  6677.         clk=0;
  6678.         superman = 1;
  6679.         fading=fade_flicker;
  6680.         count_enemy=false;
  6681.         dir=down;
  6682.        
  6683.         if(!canmove(down,(fix)8,spw_none))
  6684.             clk3=int(13.0/step);
  6685.     }
  6686.     else if(flags & guy_fadeinstant)
  6687.     {
  6688.         clk=0;
  6689.     }
  6690.    
  6691.     shadowdistance = 0;
  6692.     clk4 = clk5 = 0;
  6693.     //nets+2380;
  6694. }
  6695.  
  6696. bool eStalfos::animate(int index)
  6697. {
  6698.     if(dying)
  6699.     {
  6700.         if(haslink)
  6701.         {
  6702.             Link.setEaten(0);
  6703.             haslink=false;
  6704.         }
  6705.        
  6706.         if(dmisc9==e9tROPE && dmisc2==e2tBOMBCHU && !fired && hp<=0 && hp>-1000 && wpn>wEnemyWeapons)
  6707.         {
  6708.             hp=-1000;
  6709. //        weapon *ew=new weapon(x,y,z, ewBomb, 0, d->wdp, dir);
  6710.             weapon *ew=new weapon(x,y,z, wpn, 0, dmisc4, dir,-1,getUID(),false);
  6711.             Ewpns.add(ew);
  6712.            
  6713.             if(wpn==ewSBomb || wpn==ewBomb)
  6714.             {
  6715.                 ew->step=0;
  6716.                 ew->id=wpn;
  6717.                 ew->misc=50;
  6718.                 ew->clk=48;
  6719.             }
  6720.            
  6721.             fired=true;
  6722.         }
  6723.         else if(wpn && wpn!=ewBrang && dmisc2==e2tFIREOCTO)  // Fire Octo
  6724.         {
  6725.             if(!dummy_bool[0])
  6726.             {
  6727.                 int wpn2 = wpn+dmisc3;
  6728.                
  6729.                 if(wpn2 <= wEnemyWeapons || wpn2 >= wMax)
  6730.                 {
  6731.                     wpn2=wpn;
  6732.                 }
  6733.                
  6734.                 dummy_bool[0]=true;
  6735.                 addEwpn(x,y,z,wpn2,0,dmisc4,up, getUID());
  6736.                 addEwpn(x,y,z,wpn2,0,dmisc4,down, getUID());
  6737.                 addEwpn(x,y,z,wpn2,0,dmisc4,left, getUID());
  6738.                 addEwpn(x,y,z,wpn2,0,dmisc4,right, getUID());
  6739.                 addEwpn(x,y,z,wpn2,0,dmisc4,l_up, getUID());
  6740.                 addEwpn(x,y,z,wpn2,0,dmisc4,r_up, getUID());
  6741.                 addEwpn(x,y,z,wpn2,0,dmisc4,l_down, getUID());
  6742.                 addEwpn(x,y,z,wpn2,0,dmisc4,r_down, getUID());
  6743.                 Backend::sfx->play(wpnsfx(wpn2),int(x));
  6744.             }
  6745.         }
  6746.        
  6747.         KillWeapon();
  6748.         return Dead(index);
  6749.     }
  6750.     else if((hp<=0 && dmisc2==e2tSPLIT) || (dmisc2==e2tSPLITHIT && hp>0 && hp<guysbuf[id&0xFFF].hp && !slide()))  //Split into enemies
  6751.     {
  6752.         stop_bgsfx(index);
  6753.         int kids = guys.Count();
  6754.         int id2=dmisc3;
  6755.        
  6756.         for(int i=0; i < dmisc4; i++)
  6757.         {
  6758. //      if (addenemy(x,y,id2+(guysbuf[id2].family==eeKEESE ? 0 : ((i+1)<<12)),-21-(i%4)))
  6759.             if(addenemy(x,y,id2+(guysbuf[id2].family==eeKEESE ? 0 : (i<<12)),-21-(i%4)))
  6760.                 ((enemy*)guys.spr(kids+i))->count_enemy = false;
  6761.         }
  6762.        
  6763.         if(itemguy) // Hand down the carried item
  6764.         {
  6765.             guycarryingitem = guys.Count()-1;
  6766.             ((enemy*)guys.spr(guycarryingitem))->itemguy = true;
  6767.             itemguy = false;
  6768.         }
  6769.        
  6770.         if(haslink)
  6771.         {
  6772.             Link.setEaten(0);
  6773.             haslink=false;
  6774.         }
  6775.        
  6776.         if(deadsfx > 0 && dmisc2==e2tSPLIT)
  6777.             Backend::sfx->play(deadsfx,int(x));
  6778.            
  6779.         return true;
  6780.     }
  6781.    
  6782.     if(fading)
  6783.     {
  6784.         if(++clk4 > 60)
  6785.         {
  6786.             clk4=0;
  6787.             superman=0;
  6788.             fading=0;
  6789.            
  6790.             if(flags2&cmbflag_armos && z==0)
  6791.                 removearmos(x,y);
  6792.                
  6793.             clk2=0;
  6794.            
  6795.             newdir();
  6796.         }
  6797.         else return enemy::animate(index);
  6798.     }
  6799.     else if(flags2&cmbflag_armos && z==0 && clk==0)
  6800.         removearmos(x,y);
  6801.        
  6802.     if(haslink)
  6803.     {
  6804.         Link.setX(x);
  6805.         Link.setY(y);
  6806.         ++clk2;
  6807.        
  6808.         if(clk2==(dmisc8==0 ? 95 : dmisc8))
  6809.         {
  6810.             switch(dmisc7)
  6811.             {
  6812.             case e7tEATITEMS:
  6813.             {
  6814.                 for(int i=0; i<MAXITEMS; i++)
  6815.                 {
  6816.                     if(itemsbuf[i].flags&ITEM_EDIBLE)
  6817.                         game->set_item(i, false);
  6818.                 }
  6819.                
  6820.                 break;
  6821.             }
  6822.            
  6823.             case e7tEATMAGIC:
  6824.                 game->change_dmagic(-1*game->get_magicdrainrate());
  6825.                 break;
  6826.                
  6827.             case e7tEATRUPEES:
  6828.                 game->change_drupy(-1);
  6829.                 break;
  6830.             }
  6831.            
  6832.             clk2=0;
  6833.         }
  6834.        
  6835.         if((clk&0x18)==8)                                       // stop its animation on the middle frame
  6836.             --clk;
  6837.     }
  6838.     else if(!(wpn==ewBrang && WeaponOut()))  //WeaponOut uses misc
  6839.     {
  6840.         // Movement engine
  6841.         if(clk>=0) switch(id>>12)
  6842.             {
  6843.             case 0: // Normal movement
  6844.            
  6845.                 /*
  6846.                 if((dmisc9==e9tLEEVER || dmisc9==e9tZ3LEEVER) && !slide()) //Leever
  6847.                 {
  6848.                   // Overloading clk4 (Tribble clock) here...
  6849.                   step=17/100.0;
  6850.                   if(clk4<32)    misc=1;
  6851.                   else if(clk4<48)    misc=2;
  6852.                   else if(clk4<300) { misc=3; step = dstep/100.0; }
  6853.                   else if(clk4<316)   misc=2;
  6854.                   else if(clk4<412)   misc=1;
  6855.                   else if(clk4<540) { misc=0; step=0; }
  6856.                   else clk4=0;
  6857.                   if(clk4==48) clk=0;
  6858.                   hxofs=(misc>=2)?0:1000;
  6859.                   if (dmisc9==e9tLEEVER)
  6860.                     variable_walk(rate, homing, 0);
  6861.                   else
  6862.                     variable_walk_8(rate, homing, 4, 0);
  6863.                   break;
  6864.                 }
  6865.                 */
  6866.                 if(dmisc9==e9tVIRE || dmisc9==e9tPOLSVOICE) //Vire
  6867.                 {
  6868.                     vire_hop();
  6869.                     break;
  6870.                 }
  6871.                 else if(dmisc9==e9tROPE) //Rope charge
  6872.                 {
  6873.                     if(!fired && dashing && !stunclk && !watch)
  6874.                     {
  6875.                         if(dmisc2==e2tBOMBCHU && LinkInRange(16) && wpn+dmisc3 > wEnemyWeapons) //Bombchu
  6876.                         {
  6877.                             hp=-1000;
  6878.                            
  6879.                             int wpn2;
  6880.                             if(wpn+dmisc3 > wEnemyWeapons && wpn+dmisc3 < wMax)
  6881.                                 wpn2=wpn;
  6882.                             else
  6883.                                 wpn2=wpn;
  6884.                            
  6885.                             weapon *ew=new weapon(x,y,z, wpn2, 0, dmisc4, dir,-1,getUID());
  6886.                             Ewpns.add(ew);
  6887.                            
  6888.                             if(wpn2==ewSBomb || wpn2==ewBomb)
  6889.                             {
  6890.                                 ew->step=0;
  6891.                                 ew->id=wpn2;
  6892.                                 ew->misc=50;
  6893.                                 ew->clk=48;
  6894.                             }
  6895.                            
  6896.                             fired=true;
  6897.                         }
  6898.                     }
  6899.                    
  6900.                     charge_attack();
  6901.                     break;
  6902.                 }
  6903.                 /*
  6904.                  * Boomerang-throwers have a halt count of 1
  6905.                  * Zols have a halt count of (rand()&7)<<4
  6906.                  * Gels have a halt count of ((rand()&7)<<3)+2
  6907.                  * Everything else has 48
  6908.                  */
  6909.                 else
  6910.                 {
  6911.                     if(wpn==ewBrang) // Goriya
  6912.                     {
  6913.                         halting_walk(rate,homing,0,hrate, 1);
  6914.                     }
  6915.                     else if(dmisc9==e9tNORMAL && wpn==0)
  6916.                     {
  6917.                         if(dmisc2==e2tSPLITHIT) // Zol
  6918.                         {
  6919.                             halting_walk(rate,homing,0,hrate,(rand()&7)<<4);
  6920.                         }
  6921.                         else if(frate<=8 && starting_hp==1) // Gel
  6922.                         {
  6923.                             halting_walk(rate,homing,0,hrate,((rand()&7)<<3)+2);
  6924.                         }
  6925.                         else // Other
  6926.                         {
  6927.                             halting_walk(rate,homing,0,hrate, 48);
  6928.                         }
  6929.                     }
  6930.                     else // Other
  6931.                     {
  6932.                         halting_walk(rate,homing,0,hrate, 48);
  6933.                     }
  6934.                 }
  6935.                
  6936.                 //if not in midair, and Link's swinging sword is nearby, jump.
  6937.                 /*if (dmisc9==e9tZ3STALFOS && z==0 && (!(tmpscr->flags7&fSIDEVIEW) || !_walkflag(x,y+16,0))
  6938.                   && Link.getAttackClk()==5 && Link.getAttack()==wSword && distance(x,y,Link.getX(),Link.getY())<32)
  6939.                     {
  6940.                       facelink(false);
  6941.                       sclk=16+((dir^1)<<8);
  6942.                     fall=-FEATHERJUMP;
  6943.                       sfx(WAV_ZN1JUMP,pan(int(x)));
  6944.                     }*/
  6945.                 break;
  6946.                
  6947.                 // Following cases are for just after creation-by-splitting.
  6948.             case 1:
  6949.                 if(misc==1)
  6950.                 {
  6951.                     dir=up;
  6952.                     step=8;
  6953.                 }
  6954.                
  6955.                 if(misc<=2)
  6956.                 {
  6957.                     move(step);
  6958.                    
  6959.                     if(!canmove(dir,(fix)0,0))
  6960.                         dir=down;
  6961.                 }
  6962.                
  6963.                 if(misc==3)
  6964.                 {
  6965.                     if(canmove(right,(fix)16,0))
  6966.                         x+=16;
  6967.                 }
  6968.                
  6969.                 ++misc;
  6970.                 break;
  6971.                
  6972.             case 2:
  6973.                 if(misc==1)
  6974.                 {
  6975.                     dir=down;
  6976.                     step=8;
  6977.                 }
  6978.                
  6979.                 if(misc<=2)
  6980.                 {
  6981.                     move(step);
  6982.                     /*
  6983.                               if(!canmove(dir,(fix)0,0))
  6984.                                 dir=up;
  6985.                     */
  6986.                 }
  6987.                
  6988.                 if(misc==3)
  6989.                 {
  6990.                     if(canmove(left,(fix)16,0))
  6991.                         x-=16;
  6992.                 }
  6993.                
  6994.                 ++misc;
  6995.                 break;
  6996.                
  6997.             default:
  6998.                 if(misc==1)
  6999.                 {
  7000.                     dir=(rand()%4);
  7001.                     step=8;
  7002.                 }
  7003.                
  7004.                 if(misc<=2)
  7005.                 {
  7006.                     move(step);
  7007.                    
  7008.                     if(!canmove(dir,(fix)0,0))
  7009.                         dir=dir^1;
  7010.                 }
  7011.                
  7012.                 if(misc==3)
  7013.                 {
  7014.                     if(dir >= left && canmove(dir,(fix)16,0))
  7015.                         x+=(dir==left ? -16 : 16);
  7016.                 }
  7017.                
  7018.                 ++misc;
  7019.                 break;
  7020.             }
  7021.            
  7022.         if(id>>12 && misc>=4) //recently spawned by a split enemy
  7023.         {
  7024.             id&=0xFFF;
  7025.             step = dstep/100.0;
  7026.            
  7027.             if(x<32) x=32;
  7028.            
  7029.             if(x>208) x=208;
  7030.            
  7031.             if(y<32) y=32;
  7032.            
  7033.             if(y>128) y=128;
  7034.            
  7035.             misc=3;
  7036.         }
  7037.     }
  7038.     else
  7039.     {
  7040.         //sfx(wpnsfx(wpn),pan(int(x)));
  7041.         if(clk2>2) clk2--;
  7042.     }
  7043.    
  7044.     // Fire Zol
  7045.     if(wpn && dmisc1==e1tEACHTILE && clk2==1 && !hclk)
  7046.     {
  7047.         addEwpn(x,y,z,wpn,0,wdp,dir, getUID());
  7048.         Backend::sfx->play(wpnsfx(wpn),int(x));
  7049.        
  7050.         int i=Ewpns.Count()-1;
  7051.         weapon *ew = (weapon*)(Ewpns.spr(i));
  7052.        
  7053.         if(wpn==ewFIRETRAIL && wpnsbuf[ewFIRETRAIL].frames>1)
  7054.         {
  7055.             ew->aframe=rand()%wpnsbuf[ewFIRETRAIL].frames;
  7056.             ew->tile+=ew->aframe;
  7057.         }
  7058.     }
  7059.     // Goriya
  7060.     else if(wpn==ewBrang && clk2==1 && sclk==0 && !stunclk && !watch && wpn && !WeaponOut())
  7061.     {
  7062.         misc=index+100;
  7063.         Ewpns.add(new weapon(x,y,z,wpn,misc,wdp,dir, -1,getUID(),false));
  7064.         ((weapon*)Ewpns.spr(Ewpns.Count()-1))->dummy_bool[0]=false;
  7065.        
  7066.         if(dmisc1==2)
  7067.         {
  7068.             int ndir=dir;
  7069.            
  7070.             if(Link.x-x==0)
  7071.             {
  7072.                 ndir=(Link.y+8<y)?up:down;
  7073.             }
  7074.             else //turn to face Link
  7075.             {
  7076.                 double ddir=atan2(double(y-(Link.y)),double(Link.x-x));
  7077.                
  7078.                 if((ddir<=(((-2)*PI)/8))&&(ddir>(((-6)*PI)/8)))
  7079.                 {
  7080.                     ndir=down;
  7081.                 }
  7082.                 else if((ddir<=(((2)*PI)/8))&&(ddir>(((-2)*PI)/8)))
  7083.                 {
  7084.                     ndir=right;
  7085.                 }
  7086.                 else if((ddir<=(((6)*PI)/8))&&(ddir>(((2)*PI)/8)))
  7087.                 {
  7088.                     ndir=up;
  7089.                 }
  7090.                 else
  7091.                 {
  7092.                     ndir=left;
  7093.                 }
  7094.             }
  7095.            
  7096.             ((weapon*)Ewpns.spr(Ewpns.Count()-1))->dummy_bool[0]=true;
  7097.            
  7098.             if(canmove(ndir))
  7099.             {
  7100.                 dir=ndir;
  7101.             }
  7102.         }
  7103.     }
  7104.     else if((clk2==16 || dmisc1==e1tCONSTANT) &&  dmisc1!=e1tEACHTILE && wpn && wpn!=ewBrang && sclk==0 && !stunclk && !watch)
  7105.         switch(dmisc1)
  7106.         {
  7107.         case e1tCONSTANT: //Deathnut
  7108.         {
  7109.             // Overloading clk5 (Like Like clock) to avoid making another clock just for this attack...
  7110.             if(clk5>64)
  7111.             {
  7112.                 clk5=0;
  7113.                 fired=false;
  7114.             }
  7115.            
  7116.             clk5+=(rand()&3);
  7117.            
  7118.             if((clk5>24)&&(clk5<52))
  7119.             {
  7120.                 tile+=20;                                         //firing
  7121.                
  7122.                 if(!fired&&(clk5>=38))
  7123.                 {
  7124.                     Ewpns.add(new weapon(x,y,z, wpn, 0, wdp, dir, -1,getUID(),false));
  7125.                     Backend::sfx->play(wpnsfx(wpn),int(x));
  7126.                     fired=true;
  7127.                 }
  7128.             }
  7129.            
  7130.             break;
  7131.         }
  7132.        
  7133.         case e1tFIREOCTO: //Fire Octo
  7134.             timer=rand()%50+50;
  7135.             break;
  7136.            
  7137.         default:
  7138.             FireWeapon();
  7139.             break;
  7140.         }
  7141.        
  7142.     /* Fire again if:
  7143.      * - clk2 about to run out
  7144.      * - not already double-firing (dmisc1 is 1)
  7145.      * - not carrying Link
  7146.      * - one in 0xF chance
  7147.      */
  7148.     if(clk2==1 && (multishot < dmisc6) && dmisc1 != e1tEACHTILE && !haslink && !(rand()&15))
  7149.     {
  7150. #if 1
  7151.         newdir(rate, homing, grumble);
  7152. #else
  7153.         dir^=2;
  7154. #endif
  7155.         clk2=28;
  7156.         ++multishot;
  7157.     }
  7158.    
  7159.     if(clk2==0)
  7160.     {
  7161.         multishot = 0;
  7162.     }
  7163.    
  7164.     if(timer)  //Fire Octo
  7165.     {
  7166.         clk2=15; //this keeps the octo in place until he's done firing
  7167.        
  7168.         if(!(timer%4))
  7169.         {
  7170.             FireBreath(false);
  7171.         }
  7172.        
  7173.         --timer;
  7174.     }
  7175.    
  7176.     if(dmisc2==e2tTRIBBLE)
  7177.         ++clk4;
  7178.        
  7179.     if(clk4==(dmisc5 ? dmisc5 : 256) && (dmisc2==e2tTRIBBLE) && dmisc3 && dmisc4)
  7180.     {
  7181.         int kids = guys.Count();
  7182.         int id2=dmisc3;
  7183.        
  7184.         for(int i=0; i<dmisc4; i++)
  7185.         {
  7186.             if(addenemy(x,y,id2,-24))
  7187.             {
  7188.                 if(itemguy) // Hand down the carried item
  7189.                 {
  7190.                     guycarryingitem = guys.Count()-1;
  7191.                     ((enemy*)guys.spr(guycarryingitem))->itemguy = true;
  7192.                     itemguy = false;
  7193.                 }
  7194.                
  7195.                 ((enemy*)guys.spr(kids+i))->count_enemy = false;
  7196.             }
  7197.         }
  7198.        
  7199.         if(haslink)
  7200.         {
  7201.             Link.setEaten(0);
  7202.             haslink=false;
  7203.         }
  7204.        
  7205.         stop_bgsfx(index);
  7206.         return true;
  7207.     }
  7208.    
  7209.     return enemy::animate(index);
  7210. }
  7211.  
  7212. void eStalfos::draw(BITMAP *dest)
  7213. {
  7214.     /*if ((dmisc9==e9tLEEVER || dmisc9==e9tZ3LEEVER) && misc<=0) //Submerged
  7215.     {
  7216.       clk4--; //Kludge
  7217.       return;
  7218.     }*/
  7219.    
  7220.     /*if ((dmisc9==e9tLEEVER || dmisc9==e9tZ3LEEVER) && misc>1)
  7221.     {
  7222.       cs = dcset;
  7223.     }*/
  7224.     update_enemy_frame();
  7225.    
  7226.     if((dmisc2==e2tBOMBCHU)&&dashing)
  7227.     {
  7228.         tile+=20;
  7229.     }
  7230.    
  7231.     enemy::draw(dest);
  7232. }
  7233.  
  7234. void eStalfos::drawshadow(BITMAP *dest, bool translucent)
  7235. {
  7236.     int tempy=yofs;
  7237.    
  7238.     /*
  7239.       if (clk6 && dir>=left && !get_bit(quest_rules,qr_ENEMIESZAXIS)) {
  7240.         flip = 0;
  7241.         int f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
  7242.           (clk/(frate/4)):((clk>=(frate>>1))?1:0);
  7243.         shadowtile = wpnsbuf[iwShadow].tile+f2;
  7244.         yofs+=(((int)y+17)&0xF0)-y;
  7245.         yofs+=8;
  7246.       }
  7247.     */
  7248.     if((dmisc9 == e9tPOLSVOICE || dmisc9==e9tVIRE) && !get_bit(quest_rules,qr_ENEMIESZAXIS))
  7249.     {
  7250.         flip = 0;
  7251.         int fdiv = frate/4;
  7252.         int efrate = fdiv == 0 ? 0 : clk/fdiv;
  7253.        
  7254.         int f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
  7255.                efrate:((clk>=(frate>>1))?1:0);
  7256.         shadowtile = wpnsbuf[iwShadow].tile;
  7257.        
  7258.         if(get_bit(quest_rules,qr_NEWENEMYTILES))
  7259.         {
  7260.             shadowtile+=f2;
  7261.         }
  7262.         else
  7263.         {
  7264.             shadowtile+=f2?1:0;
  7265.         }
  7266.        
  7267.         yofs+=shadowdistance;
  7268.         yofs+=8;
  7269.     }
  7270.    
  7271.     enemy::drawshadow(dest, translucent);
  7272.     yofs=tempy;
  7273. }
  7274.  
  7275. int eStalfos::takehit(weapon *w)
  7276. {
  7277.     int wpnId = w->id;
  7278.     int wpnDir = w->dir;
  7279.    
  7280.     if(wpnId==wHammer && shield && (flags & guy_bkshield)
  7281.             && ((flags&inv_front && wpnDir==(dir^down)) || (flags&inv_back && wpnDir==(dir^up))
  7282.                 || (flags&inv_left && wpnDir==(dir^left)) || (flags&inv_right && wpnDir==(dir^right))))
  7283.     {
  7284.         shield = false;
  7285.         flags &= ~(inv_left|inv_right|inv_back|inv_front);
  7286.        
  7287.         if(get_bit(quest_rules,qr_BRKNSHLDTILES))
  7288.             o_tile=s_tile;
  7289.     }
  7290.    
  7291.     int ret = enemy::takehit(w);
  7292.    
  7293.     if(sclk && dmisc2==e2tSPLITHIT)
  7294.         sclk+=128;
  7295.        
  7296.     return ret;
  7297. }
  7298.  
  7299. void eStalfos::charge_attack()
  7300. {
  7301.     if(slide())
  7302.         return;
  7303.        
  7304.     if(clk<0 || dir<0 || stunclk || watch || ceiling)
  7305.         return;
  7306.        
  7307.     if(clk3<=0)
  7308.     {
  7309.         fix_coords(true);
  7310.        
  7311.         if(!dashing)
  7312.         {
  7313.             int ldir = lined_up(7,false);
  7314.            
  7315.             if(ldir!=-1 && canmove(ldir))
  7316.             {
  7317.                 dir=ldir;
  7318.                 dashing=true;
  7319.                 step=(dstep/100.0)+1;
  7320.             }
  7321.             else newdir(4,0,0);
  7322.         }
  7323.        
  7324.         if(!canmove(dir))
  7325.         {
  7326.             step=dstep/100.0;
  7327.             newdir();
  7328.             dashing=false;
  7329.         }
  7330.        
  7331.         fix div = step;
  7332.        
  7333.         if(div == 0)
  7334.             div = 1;
  7335.            
  7336.         clk3=(int)(16.0/div);
  7337.         return;
  7338.     }
  7339.    
  7340.     move(step);
  7341.     --clk3;
  7342. }
  7343.  
  7344. void eStalfos::vire_hop()
  7345. {
  7346.     if(dmisc9!=e9tPOLSVOICE)
  7347.     {
  7348.         if(sclk!=0)
  7349.             return;
  7350.     }
  7351.     else sclk=0;
  7352.    
  7353.     if(clk<0 || dying || stunclk || watch || ceiling)
  7354.         return;
  7355.        
  7356.     int jump_width;
  7357.     int jump_height;
  7358.    
  7359.     if(dmisc9==e9tPOLSVOICE)
  7360.     {
  7361.         jump_width=2;
  7362.         jump_height=27;
  7363.     }
  7364.     else
  7365.     {
  7366.         jump_width=1;
  7367.         jump_height=16;
  7368.     }
  7369.    
  7370.     y=floor_y;
  7371.    
  7372.     if(clk3<=0)
  7373.     {
  7374.         fix_coords();
  7375.        
  7376.         //z=0;
  7377.         //if we're not in the middle of a jump or if we can't complete the current jump in the current direction
  7378.         if(clk2<=0 || !canmove(dir,(fix)1,spw_floater) || (tmpscr->flags7&fSIDEVIEW && ON_SIDEPLATFORM))
  7379.             newdir(rate,homing,dmisc9==e9tPOLSVOICE ? spw_floater : spw_none);
  7380.            
  7381.         if(clk2<=0)
  7382.         {
  7383.             //z=0;
  7384.             if(!canmove(dir,(fix)2,spw_none) || m_walkflag(x,y,spw_none) || (rand()&15)>=hrate)
  7385.                 clk2=(wpn==ewBrang ? 1 : 16*jump_width/step);
  7386.         }
  7387.        
  7388.         if(dmisc9!=e9tPOLSVOICE && dir>=left) //if we're moving left or right
  7389.         {
  7390.             clk2=16*jump_width/step;
  7391.         }
  7392.        
  7393.         clk3=int(16.0/step);
  7394.     }
  7395.    
  7396.     --clk3;
  7397.    
  7398.     if(dmisc9==e9tPOLSVOICE || clk2>0)
  7399.         move(step);
  7400.        
  7401.     floor_y=y;
  7402.     clk2--;
  7403.    
  7404.     //if we're in the middle of a jump
  7405.     if(clk2>0 && (dir>=left || dmisc9==e9tPOLSVOICE))
  7406.     {
  7407.         int h = fixtoi(fixsin(itofix(clk2*128*step/(16*jump_width)))*jump_height);
  7408.        
  7409.         if(get_bit(quest_rules,qr_ENEMIESZAXIS) && !(tmpscr->flags7&fSIDEVIEW))
  7410.         {
  7411.             z=h;
  7412.         }
  7413.         else
  7414.         {
  7415.             //y+=fixtoi(fixsin(itofix((clk2+1)*128*step/(16*jump_width)))*jump_height);
  7416.             //y-=h;
  7417.             y=floor_y-h;
  7418.             shadowdistance=h;
  7419.         }
  7420.     }
  7421.     else
  7422.         shadowdistance = 0;
  7423. }
  7424.  
  7425. void eStalfos::eatlink()
  7426. {
  7427.     if(!haslink && Link.getEaten()==0 && Link.getAction() != hopping && Link.getAction() != swimming)
  7428.     {
  7429.         haslink=true;
  7430.         y=floor_y;
  7431.         z=0;
  7432.        
  7433.         if(Link.isSwimming())
  7434.         {
  7435.             Link.setX(x);
  7436.             Link.setY(y);
  7437.         }
  7438.         else
  7439.         {
  7440.             x=Link.getX();
  7441.             y=Link.getY();
  7442.         }
  7443.        
  7444.         clk2=0;
  7445.     }
  7446. }
  7447.  
  7448. bool eStalfos::WeaponOut()
  7449. {
  7450.     for(int i=0; i<Ewpns.Count(); i++)
  7451.     {
  7452.         if(((weapon*)Ewpns.spr(i))->parentid==getUID() && Ewpns.spr(i)->id==ewBrang)
  7453.         {
  7454.             return true;
  7455.         }
  7456.        
  7457.         /*if (bgsfx > 0 && guys.idCount(id) < 2) // count self
  7458.           stop_sfx(bgsfx);
  7459.         */
  7460.     }
  7461.    
  7462.     return false;
  7463. }
  7464.  
  7465. void eStalfos::KillWeapon()
  7466. {
  7467.     for(int i=0; i<Ewpns.Count(); i++)
  7468.     {
  7469.         if(((weapon*)Ewpns.spr(i))->type==misc && Ewpns.spr(i)->id==ewBrang)
  7470.         {
  7471.             //only kill this Goriya's boomerang -DD
  7472.             if(((weapon *)Ewpns.spr(i))->parentid == getUID())
  7473.             {
  7474.                 Ewpns.del(i);
  7475.             }
  7476.         }
  7477.     }
  7478.    
  7479.     if(wpn==ewBrang && !Ewpns.idCount(ewBrang))
  7480.     {
  7481.         Backend::sfx->stop(WAV_BRANG);
  7482.     }
  7483. }
  7484.  
  7485. void eStalfos::break_shield()
  7486. {
  7487.     if(!shield)
  7488.         return;
  7489.        
  7490.     flags&=~(inv_front | inv_back | inv_left | inv_right);
  7491.     shield=false;
  7492.    
  7493.     if(get_bit(quest_rules,qr_BRKNSHLDTILES))
  7494.         o_tile=s_tile;
  7495. }
  7496.  
  7497. eKeese::eKeese(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  7498. {
  7499.     dir=(rand()&7)+8;
  7500.     step=0;
  7501.     movestatus=1;
  7502.     c=0;
  7503.     hxofs=2;
  7504.     hxsz=12;
  7505.     hyofs=4;
  7506.     hysz=8;
  7507.     clk4=0;
  7508.     //nets;
  7509.     dummy_int[1]=0;
  7510. }
  7511.  
  7512. bool eKeese::animate(int index)
  7513. {
  7514.     if(dying)
  7515.         return Dead(index);
  7516.        
  7517.     if(clk==0)
  7518.     {
  7519.         removearmos(x,y);
  7520.     }
  7521.    
  7522.     if(dmisc1)
  7523.     {
  7524.         floater_walk(rate,hrate,dstep/100,(fix)0,10,0,0);
  7525.     }
  7526.     else
  7527.     {
  7528.         floater_walk(rate,hrate,dstep/100,dstep/1000,10,120,16);
  7529.     }
  7530.    
  7531.     if(dmisc2 == e2tKEESETRIB)
  7532.     {
  7533.         if(++clk4==256)
  7534.         {
  7535.             if(!m_walkflag(x,y,0))
  7536.             {
  7537.                 int kids = guys.Count();
  7538.                 bool success = false;
  7539.                 int id2=dmisc3;
  7540.                 success = 0 != addenemy((fix)x,(fix)y,id2,-24);
  7541.                
  7542.                 if(success)
  7543.                 {
  7544.                     if(itemguy) // Hand down the carried item
  7545.                     {
  7546.                         guycarryingitem = guys.Count()-1;
  7547.                         ((enemy*)guys.spr(guycarryingitem))->itemguy = true;
  7548.                         itemguy = false;
  7549.                     }
  7550.                    
  7551.                     ((enemy*)guys.spr(kids))->count_enemy = count_enemy;
  7552.                 }
  7553.                
  7554.                 stop_bgsfx(index);
  7555.                 return true;
  7556.             }
  7557.             else
  7558.             {
  7559.                 clk4=0;
  7560.             }
  7561.         }
  7562.     }
  7563.     // Keese Tribbles stay on the ground, so there's no problem when they transform.
  7564.     else if(get_bit(quest_rules,qr_ENEMIESZAXIS) && !(tmpscr->flags7&fSIDEVIEW))
  7565.     {
  7566.         z=int(step/(dstep/100.0));
  7567.         // Some variance in keese flight heights when away from Link
  7568.         z+=int(step*zc_max(0,(distance(x,y,LinkX(),LinkY())-128)/10));
  7569.     }
  7570.    
  7571.     return enemy::animate(index);
  7572. }
  7573.  
  7574. void eKeese::drawshadow(BITMAP *dest, bool translucent)
  7575. {
  7576.     int tempy=yofs;
  7577.     flip = 0;
  7578.     shadowtile = wpnsbuf[iwShadow].tile+posframe;
  7579.     yofs+=8;
  7580.    
  7581.     if(!get_bit(quest_rules,qr_ENEMIESZAXIS))
  7582.         yofs+=int(step/(dstep/1000.0));
  7583.        
  7584.     enemy::drawshadow(dest, translucent);
  7585.     yofs=tempy;
  7586. }
  7587.  
  7588. void eKeese::draw(BITMAP *dest)
  7589. {
  7590.     update_enemy_frame();
  7591.     enemy::draw(dest);
  7592. }
  7593.  
  7594. eWizzrobe::eWizzrobe(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  7595. {
  7596. //  switch(d->misc1)
  7597.     switch(dmisc1)
  7598.     {
  7599.     case 0:
  7600.         hxofs=1000;
  7601.         fading=fade_invisible;
  7602.         // Set clk to just before the 'reappear' threshold
  7603.         clk=zc_min(clk+(146+zc_max(0,dmisc5))+14,(146+zc_max(0,dmisc5))-1);
  7604.         break;
  7605.        
  7606.     default:
  7607.         dir=(loadside==right)?right:left;
  7608.         misc=-3;
  7609.         break;
  7610.     }
  7611.    
  7612.     //netst+2880;
  7613.     charging=false;
  7614.     firing=false;
  7615.     fclk=0;
  7616.    
  7617.     if(!dmisc1) frate=1200+146; //1200 = 20 seconds
  7618. }
  7619.  
  7620. bool eWizzrobe::animate(int index)
  7621. {
  7622.     if(dying)
  7623.     {
  7624.         return Dead(index);
  7625.     }
  7626.    
  7627.     if(clk==0)
  7628.     {
  7629.         removearmos(x,y);
  7630.     }
  7631.    
  7632.     if(dmisc1) // Floating
  7633.     {
  7634.         wizzrobe_attack();
  7635.     }
  7636.     else // Teleporting
  7637.     {
  7638.         if(watch)
  7639.         {
  7640.             fading=0;
  7641.             hxofs=0;
  7642.         }
  7643.         else switch(clk)
  7644.             {
  7645.             case 0:
  7646.                 if(!dmisc2)
  7647.                 {
  7648.                     place_on_axis(true, dmisc4!=0);
  7649.                 }
  7650.                 else
  7651.                 {
  7652.                     int t=0;
  7653.                     bool placed=false;
  7654.                    
  7655.                     while(!placed && t<160)
  7656.                     {
  7657.                         if(isdungeon())
  7658.                         {
  7659.                             x=((rand()%12)+2)*16;
  7660.                             y=((rand()%7)+2)*16;
  7661.                         }
  7662.                         else
  7663.                         {
  7664.                             x=((rand()%14)+1)*16;
  7665.                             y=((rand()%9)+1)*16;
  7666.                         }
  7667.                        
  7668.                         if(!m_walkflag(x,y,spw_door)&&((abs(x-Link.getX())>=32)||(abs(y-Link.getY())>=32)))
  7669.                         {
  7670.                             placed=true;
  7671.                         }
  7672.                        
  7673.                         ++t;
  7674.                     }
  7675.                    
  7676.                     if(abs(x-Link.getX())<abs(y-Link.getY()))
  7677.                     {
  7678.                         if(y<Link.getY())
  7679.                         {
  7680.                             dir=down;
  7681.                         }
  7682.                         else
  7683.                         {
  7684.                             dir=up;
  7685.                         }
  7686.                     }
  7687.                     else
  7688.                     {
  7689.                         if(x<Link.getX())
  7690.                         {
  7691.                             dir=right;
  7692.                         }
  7693.                         else
  7694.                         {
  7695.                             dir=left;
  7696.                         }
  7697.                     }
  7698.                    
  7699.                     if(!placed)                                       // can't place him, he's gone
  7700.                         return true;
  7701.                 }
  7702.                
  7703.                 fading=fade_flicker;
  7704.                 hxofs=0;
  7705.                 break;
  7706.                
  7707.             case 64:
  7708.                 fading=0;
  7709.                 charging=true;
  7710.                 break;
  7711.                
  7712.             case 73:
  7713.                 charging=false;
  7714.                 firing=40;
  7715.                 break;
  7716.                
  7717.             case 83:
  7718.                 wizzrobe_attack_for_real();
  7719.                 break;
  7720.                
  7721.             case 119:
  7722.                 firing=false;
  7723.                 charging=true;
  7724.                 break;
  7725.                
  7726.             case 128:
  7727.                 fading=fade_flicker;
  7728.                 charging=false;
  7729.                 break;
  7730.                
  7731.             case 146:
  7732.                 fading=fade_invisible;
  7733.                 hxofs=1000;
  7734.                
  7735.                 //Fall through
  7736.             default:
  7737.                 if(clk>=(146+zc_max(0,dmisc5)))
  7738.                     clk=-1;
  7739.                    
  7740.                 break;
  7741.             }
  7742.     }
  7743.    
  7744.     return enemy::animate(index);
  7745. }
  7746.  
  7747. void eWizzrobe::wizzrobe_attack_for_real()
  7748. {
  7749.     if(wpn==0)  // Edited enemies
  7750.         return;
  7751.        
  7752.     if(dmisc2 == 0)  //normal weapon
  7753.     {
  7754.         addEwpn(x,y,z,wpn,0,wdp,dir,getUID());
  7755.         Backend::sfx->play(WAV_WAND,int(x));
  7756.     }
  7757.     else if(dmisc2 == 1) // ring of fire
  7758.     {
  7759.         addEwpn(x,y,z,wpn,0,wdp,up,getUID());
  7760.         addEwpn(x,y,z,wpn,0,wdp,down,getUID());
  7761.         addEwpn(x,y,z,wpn,0,wdp,left,getUID());
  7762.         addEwpn(x,y,z,wpn,0,wdp,right,getUID());
  7763.         addEwpn(x,y,z,wpn,0,wdp,l_up,getUID());
  7764.         addEwpn(x,y,z,wpn,0,wdp,r_up,getUID());
  7765.         addEwpn(x,y,z,wpn,0,wdp,l_down,getUID());
  7766.         addEwpn(x,y,z,wpn,0,wdp,r_down,getUID());
  7767.         Backend::sfx->play(WAV_FIRE,int(x));
  7768.     }
  7769.     else if(dmisc2==2)  // summons specific enemy
  7770.     {
  7771.         int bc=0;
  7772.        
  7773.         for(int gc=0; gc<guys.Count(); gc++)
  7774.         {
  7775.             if((((enemy*)guys.spr(gc))->id) == dmisc3)
  7776.             {
  7777.                 ++bc;
  7778.             }
  7779.         }
  7780.        
  7781.         if(bc<=40)
  7782.         {
  7783.             int kids = guys.Count();
  7784.             int bats=(rand()%3)+1;
  7785.            
  7786.             for(int i=0; i<bats; i++)
  7787.             {
  7788.                 // Summon bats (or anything)
  7789.                 if(addenemy(x,y,dmisc3,-10))
  7790.                     ((enemy*)guys.spr(kids+i))->count_enemy = false;
  7791.             }
  7792.            
  7793.             Backend::sfx->play(WAV_FIRE,int(x));
  7794.         }
  7795.     }
  7796.     else if(dmisc2==3)  //summon from layer
  7797.     {
  7798.         if(count_layer_enemies()==0)
  7799.         {
  7800.             return;
  7801.         }
  7802.        
  7803.         int kids = guys.Count();
  7804.        
  7805.         if(kids<200)
  7806.         {
  7807.             int newguys=(rand()%3)+1;
  7808.             bool summoned=false;
  7809.            
  7810.             for(int i=0; i<newguys; i++)
  7811.             {
  7812.                 int id2=vbound(random_layer_enemy(),eSTART,eMAXGUYS-1);
  7813.                 int x2=0;
  7814.                 int y2=0;
  7815.                
  7816.                 for(int k=0; k<20; ++k)
  7817.                 {
  7818.                     x2=16*((rand()%12)+2);
  7819.                     y2=16*((rand()%7)+2);
  7820.                    
  7821.                     if(!m_walkflag(x2,y2,0) && (abs(x2-Link.getX())>=32 || abs(y2-Link.getY())>=32))
  7822.                     {
  7823.                         if(addenemy(x2,y2,get_bit(quest_rules,qr_ENEMIESZAXIS) ? 64 : 0,id2,-10))
  7824.                             ((enemy*)guys.spr(kids+i))->count_enemy = false;
  7825.                            
  7826.                         summoned=true;
  7827.                         break;
  7828.                     }
  7829.                 }
  7830.             }
  7831.            
  7832.             if(summoned)
  7833.             {
  7834.                 Backend::sfx->play(get_bit(quest_rules,qr_MORESOUNDS) ? WAV_ZN1SUMMON : WAV_FIRE,int(x));
  7835.             }
  7836.         }
  7837.     }
  7838. }
  7839.  
  7840.  
  7841. void eWizzrobe::wizzrobe_attack()
  7842. {
  7843.     if(clk<0 || dying || stunclk || watch || ceiling)
  7844.         return;
  7845.        
  7846.     if(clk3<=0 || ((clk3&31)==0 && !canmove(dir,(fix)1,spw_door) && !misc))
  7847.     {
  7848.         fix_coords();
  7849.        
  7850.         switch(misc)
  7851.         {
  7852.         case 1:                                               //walking
  7853.             if(!m_walkflag(x,y,spw_door))
  7854.                 misc=0;
  7855.             else
  7856.             {
  7857.                 clk3=16;
  7858.                
  7859.                 if(!canmove(dir,(fix)1,spw_wizzrobe))
  7860.                 {
  7861.                     wizzrobe_newdir(0);
  7862.                 }
  7863.             }
  7864.            
  7865.             break;
  7866.            
  7867.         case 2:                                               //phasing
  7868.         {
  7869.             int jx=x;
  7870.             int jy=y;
  7871.             int jdir=-1;
  7872.            
  7873.             switch(rand()&7)
  7874.             {
  7875.             case 0:
  7876.                 jx-=32;
  7877.                 jy-=32;
  7878.                 jdir=15;
  7879.                 break;
  7880.                
  7881.             case 1:
  7882.                 jx+=32;
  7883.                 jy-=32;
  7884.                 jdir=9;
  7885.                 break;
  7886.                
  7887.             case 2:
  7888.                 jx+=32;
  7889.                 jy+=32;
  7890.                 jdir=11;
  7891.                 break;
  7892.                
  7893.             case 3:
  7894.                 jx-=32;
  7895.                 jy+=32;
  7896.                 jdir=13;
  7897.                 break;
  7898.             }
  7899.            
  7900.             if(jdir>0 && jx>=32 && jx<=208 && jy>=32 && jy<=128)
  7901.             {
  7902.                 misc=3;
  7903.                 clk3=32;
  7904.                 dir=jdir;
  7905.                 break;
  7906.             }
  7907.         }
  7908.        
  7909.         case 3:
  7910.             dir&=3;
  7911.             misc=0;
  7912.            
  7913.         case 0:
  7914.             wizzrobe_newdir(64);
  7915.            
  7916.         default:
  7917.             if(!canmove(dir,(fix)1,spw_door))
  7918.             {
  7919.                 if(canmove(dir,(fix)15,spw_wizzrobe))
  7920.                 {
  7921.                     misc=1;
  7922.                     clk3=16;
  7923.                 }
  7924.                 else
  7925.                 {
  7926.                     wizzrobe_newdir(64);
  7927.                     misc=0;
  7928.                     clk3=32;
  7929.                 }
  7930.             }
  7931.             else
  7932.             {
  7933.                 clk3=32;
  7934.             }
  7935.            
  7936.             break;
  7937.         }
  7938.        
  7939.         if(misc<0)
  7940.             ++misc;
  7941.     }
  7942.    
  7943.     --clk3;
  7944.    
  7945.     switch(misc)
  7946.     {
  7947.     case 1:
  7948.     case 3:
  7949.         step=1.0;
  7950.         break;
  7951.        
  7952.     case 2:
  7953.         step=0;
  7954.         break;
  7955.        
  7956.     default:
  7957.         step=0.5;
  7958.         break;
  7959.        
  7960.     }
  7961.    
  7962.     move(step);
  7963.    
  7964. //  if(d->misc1 && misc<=0 && clk3==28)
  7965.     if(dmisc1 && misc<=0 && clk3==28)
  7966.     {
  7967.         if(dmisc2 != 1)
  7968.         {
  7969.             if(lined_up(8,false) == dir)
  7970.             {
  7971. //        addEwpn(x,y,z,wpn,0,wdp,dir,getUID());
  7972. //        sfx(WAV_WAND,pan(int(x)));
  7973.                 wizzrobe_attack_for_real();
  7974.                 fclk=30;
  7975.             }
  7976.         }
  7977.         else
  7978.         {
  7979.             if((rand()%500)>=400)
  7980.             {
  7981.                 wizzrobe_attack_for_real();
  7982.                 fclk=30;
  7983.             }
  7984.         }
  7985.     }
  7986.    
  7987.     if(misc==0 && (rand()&127)==0)
  7988.         misc=2;
  7989.        
  7990.     if(misc==2 && clk3==4)
  7991.         fix_coords();
  7992.        
  7993.     if(!(charging||firing))                               //should never be charging or firing for these wizzrobes
  7994.     {
  7995.         if(fclk>0)
  7996.         {
  7997.             --fclk;
  7998.         }
  7999.     }
  8000.    
  8001. }
  8002.  
  8003. void eWizzrobe::wizzrobe_newdir(int homing)
  8004. {
  8005.     // Wizzrobes shouldn't move to the edge of the screen;
  8006.     // if they're already there, they should move toward the center
  8007.     if(x<32)
  8008.         dir=right;
  8009.     else if(x>=224)
  8010.         dir=left;
  8011.     else if(y<32)
  8012.         dir=down;
  8013.     else if(y>=144)
  8014.         dir=up;
  8015.     else
  8016.         newdir(4,homing,spw_wizzrobe);
  8017. }
  8018.  
  8019. void eWizzrobe::draw(BITMAP *dest)
  8020. {
  8021. //  if(d->misc1 && (misc==1 || misc==3) && (clk3&1) && hp>0 && !watch && !stunclk)                          // phasing
  8022.     if(dmisc1 && (misc==1 || misc==3) && (clk3&1) && hp>0 && !watch && !stunclk)                          // phasing
  8023.         return;
  8024.        
  8025.     int tempint=dummy_int[1];
  8026.     bool tempbool1=dummy_bool[1];
  8027.     bool tempbool2=dummy_bool[2];
  8028.     dummy_int[1]=fclk;
  8029.     dummy_bool[1]=charging;
  8030.     dummy_bool[2]=firing;
  8031.     update_enemy_frame();
  8032.     dummy_int[1]=tempint;
  8033.     dummy_bool[1]=tempbool1;
  8034.     dummy_bool[2]=tempbool2;
  8035.     enemy::draw(dest);
  8036. }
  8037.  
  8038. /*********************************/
  8039. /**********   Bosses   ***********/
  8040. /*********************************/
  8041.  
  8042. eDodongo::eDodongo(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  8043. {
  8044.     fading=fade_flash_die;
  8045.     //nets+5120;
  8046.    
  8047.     if(dir==down&&y>=128)
  8048.     {
  8049.         dir=up;
  8050.     }
  8051.    
  8052.     if(dir==right&&x>=208)
  8053.     {
  8054.         dir=left;
  8055.     }
  8056. }
  8057.  
  8058. bool eDodongo::animate(int index)
  8059. {
  8060.     if(dying)
  8061.     {
  8062.         return Dead(index);
  8063.     }
  8064.    
  8065.     if(clk==0)
  8066.     {
  8067.         removearmos(x,y);
  8068.     }
  8069.    
  8070.     if(clk2)                                                  // ate a bomb
  8071.     {
  8072.         if(--clk2==0)
  8073.             hp-=misc;                                             // store bomb's power in misc
  8074.     }
  8075.     else
  8076.         constant_walk(rate,homing,spw_clipright);
  8077.        
  8078.     hxsz = (dir<=down) ? 16 : 32;
  8079.     //    hysz = (dir>=left) ? 16 : 32;
  8080.    
  8081.     return enemy::animate(index);
  8082. }
  8083.  
  8084. void eDodongo::draw(BITMAP *dest)
  8085. {
  8086.     tile=o_tile;
  8087.    
  8088.     if(clk<0)
  8089.     {
  8090.         enemy::draw(dest);
  8091.         return;
  8092.     }
  8093.    
  8094.     update_enemy_frame();
  8095.     enemy::draw(dest);
  8096.    
  8097.     if(dummy_int[1]!=0)  //additional tiles
  8098.     {
  8099.         tile+=dummy_int[1]; //second tile is previous tile
  8100.         xofs-=16;           //new xofs change
  8101.         enemy::draw(dest);
  8102.         xofs+=16;
  8103.     }
  8104.    
  8105. }
  8106.  
  8107. int eDodongo::takehit(weapon *w)
  8108. {
  8109.     int wpnId = w->id;
  8110.     int power = w->power;
  8111.     int wpnx = w->x;
  8112.     int wpny = w->y;
  8113.    
  8114.     if(dying || clk<0 || clk2>0 || (superman && !(superman>1 && wpnId==wSBomb)))
  8115.         return 0;
  8116.        
  8117.     switch(wpnId)
  8118.     {
  8119.     case wPhantom:
  8120.         return 0;
  8121.        
  8122.     case wFire:
  8123.     case wBait:
  8124.     case wWhistle:
  8125.     case wWind:
  8126.     case wSSparkle:
  8127.     case wFSparkle:
  8128.         return 0;
  8129.        
  8130.     case wLitBomb:
  8131.     case wLitSBomb:
  8132.         if(abs(wpnx-((dir==right)?x+16:x)) > 7 || abs(wpny-y) > 7)
  8133.             return 0;
  8134.            
  8135.         clk2=96;
  8136.         misc=power;
  8137.        
  8138.         if(wpnId==wLitSBomb)
  8139.             item_set=isSBOMB100;
  8140.            
  8141.         return 1;
  8142.        
  8143.     case wBomb:
  8144.     case wSBomb:
  8145.         if(abs(wpnx-((dir==right)?x+16:x)) > 8 || abs(wpny-y) > 8)
  8146.             return 0;
  8147.            
  8148.         stunclk=160;
  8149.         misc=wpnId;                                           // store wpnId
  8150.         return 1;
  8151.        
  8152.     case wSword:
  8153.         if(stunclk)
  8154.         {
  8155.             Backend::sfx->play(WAV_EHIT,int(x));
  8156.             hp=0;
  8157.             item_set = (misc==wSBomb) ? isSBOMB100 : isBOMB100;
  8158.             fading=0;                                           // don't flash
  8159.             return 1;
  8160.         }
  8161.        
  8162.     default:
  8163.         Backend::sfx->play(WAV_CHINK,int(x));
  8164.     }
  8165.    
  8166.     return 1;
  8167. }
  8168.  
  8169. eDodongo2::eDodongo2(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  8170. {
  8171.     fading=fade_flash_die;
  8172.     //nets+5180;
  8173.     previous_dir=-1;
  8174.    
  8175.     if(dir==down&&y>=128)
  8176.     {
  8177.         dir=up;
  8178.     }
  8179.    
  8180.     if(dir==right&&x>=208)
  8181.     {
  8182.         dir=left;
  8183.     }
  8184. }
  8185.  
  8186. bool eDodongo2::animate(int index)
  8187. {
  8188.     if(dying)
  8189.     {
  8190.         return Dead(index);
  8191.     }
  8192.    
  8193.     if(clk==0)
  8194.     {
  8195.         removearmos(x,y);
  8196.     }
  8197.    
  8198.     if(clk2)                                                  // ate a bomb
  8199.     {
  8200.         if(--clk2==0)
  8201.             hp-=misc;                                             // store bomb's power in misc
  8202.     }
  8203.     else
  8204.         constant_walk(rate,homing,spw_clipbottomright);
  8205.        
  8206.     hxsz = (dir<=down) ? 16 : 32;
  8207.     hysz = (dir>=left) ? 16 : 32;
  8208.     hxofs=(dir>=left)?-8:0;
  8209.     hyofs=(dir<left)?-8:0;
  8210.    
  8211.     return enemy::animate(index);
  8212. }
  8213.  
  8214. void eDodongo2::draw(BITMAP *dest)
  8215. {
  8216.     if(clk<0)
  8217.     {
  8218.         enemy::draw(dest);
  8219.         return;
  8220.     }
  8221.    
  8222.     int tempx=xofs;
  8223.     int tempy=yofs;
  8224.     update_enemy_frame();
  8225.     enemy::draw(dest);
  8226.     tile+=dummy_int[1]; //second tile change
  8227.     xofs+=dummy_int[2]; //new xofs change
  8228.     yofs+=dummy_int[3]; //new yofs change
  8229.     enemy::draw(dest);
  8230.     xofs=tempx;
  8231.     yofs=tempy;
  8232. }
  8233.  
  8234. int eDodongo2::takehit(weapon *w)
  8235. {
  8236.     int wpnId = w->id;
  8237.     int power = w->power;
  8238.     int wpnx = w->x;
  8239.     int wpny = w->y;
  8240.    
  8241.     if(dying || clk<0 || clk2>0 || superman)
  8242.         return 0;
  8243.        
  8244.     switch(wpnId)
  8245.     {
  8246.     case wPhantom:
  8247.         return 0;
  8248.        
  8249.     case wFire:
  8250.     case wBait:
  8251.     case wWhistle:
  8252.     case wWind:
  8253.     case wSSparkle:
  8254.     case wFSparkle:
  8255.         return 0;
  8256.        
  8257.     case wLitBomb:
  8258.     case wLitSBomb:
  8259.         switch(dir)
  8260.         {
  8261.         case up:
  8262.             if(abs(wpnx-x) > 7 || abs(wpny-(y-8)) > 7)
  8263.                 return 0;
  8264.                
  8265.             break;
  8266.            
  8267.         case down:
  8268.             if(abs(wpnx-x) > 7 || abs(wpny-(y+8)) > 7)
  8269.                 return 0;
  8270.                
  8271.             break;
  8272.            
  8273.         case left:
  8274.             if(abs(wpnx-(x-8)) > 7 || abs(wpny-y) > 7)
  8275.                 return 0;
  8276.                
  8277.             break;
  8278.            
  8279.         case right:
  8280.             if(abs(wpnx-(x+8)) > 7 || abs(wpny-y) > 7)
  8281.                 return 0;
  8282.                
  8283.             break;
  8284.         }
  8285.        
  8286.         //          if(abs(wpnx-((dir==right)?x+8:(dir==left)?x-8:0)) > 7 || abs(wpny-((dir==down)?y+8:(dir==up)?y-8:0)) > 7)
  8287.         //            return 0;
  8288.         clk2=96;
  8289.         misc=power;
  8290.        
  8291.         if(wpnId==wLitSBomb)
  8292.             item_set=isSBOMB100;
  8293.            
  8294.         return 1;
  8295.        
  8296.     case wBomb:
  8297.     case wSBomb:
  8298.         switch(dir)
  8299.         {
  8300.         case up:
  8301.             if(abs(wpnx-x) > 7 || abs(wpny-(y-8)) > 7)
  8302.                 return 0;
  8303.                
  8304.             break;
  8305.            
  8306.         case down:
  8307.             if(abs(wpnx-x) > 7 || abs(wpny-(y+8)) > 7)
  8308.                 return 0;
  8309.                
  8310.             break;
  8311.            
  8312.         case left:
  8313.             if(abs(wpnx-(x-8)) > 7 || abs(wpny-y) > 7)
  8314.                 return 0;
  8315.                
  8316.             break;
  8317.            
  8318.         case right:
  8319.             if(abs(wpnx-(x+8)) > 7 || abs(wpny-y) > 7)
  8320.                 return 0;
  8321.                
  8322.             break;
  8323.         }
  8324.        
  8325.         stunclk=160;
  8326.         misc=wpnId;                                           // store wpnId
  8327.         return 1;
  8328.        
  8329.     case wSword:
  8330.         if(stunclk)
  8331.         {
  8332.             Backend::sfx->play(WAV_EHIT,int(x));
  8333.             hp=0;
  8334.             item_set = (misc==wSBomb) ? isSBOMB100 : isBOMB100;
  8335.             fading=0;                                           // don't flash
  8336.             return 1;
  8337.         }
  8338.        
  8339.     default:
  8340.         Backend::sfx->play(WAV_CHINK,int(x));
  8341.     }
  8342.    
  8343.     return 1;
  8344. }
  8345.  
  8346. eAquamentus::eAquamentus(fix X,fix Y,int Id,int Clk) : enemy((fix)176,(fix)64,Id,Clk)
  8347. {
  8348.     //these are here to bypass compiler warnings about unused arguments
  8349.     X=X;
  8350.     Y=Y;
  8351.    
  8352.     if(dmisc1)
  8353.     {
  8354.         x=64;
  8355.     }
  8356.    
  8357.     //nets+5940;
  8358.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  8359.     {
  8360.     }
  8361.     else
  8362.     {
  8363.         if(dmisc1)
  8364.         {
  8365.             flip=1;
  8366.         }
  8367.     }
  8368.    
  8369.     yofs=playing_field_offset+1;
  8370.     clk3=32;
  8371.     clk2=0;
  8372.     clk4=clk;
  8373.     dir=left;
  8374. }
  8375.  
  8376. bool eAquamentus::animate(int index)
  8377. {
  8378.     if(dying)
  8379.         return Dead(index);
  8380.        
  8381.     //  fbx=x+((id==eRAQUAM)?4:-4);
  8382.     if(clk==0)
  8383.     {
  8384.         removearmos(x,y);
  8385.     }
  8386.    
  8387.     fbx=x;
  8388.    
  8389.     /*
  8390.       if (get_bit(quest_rules,qr_NEWENEMYTILES)&&id==eLAQUAM)
  8391.       {
  8392.       fbx+=16;
  8393.       }
  8394.       */
  8395.     if(--clk3==0)
  8396.     {
  8397. //    addEwpn(fbx,y,z,ewFireball,0,d->wdp,up+1);
  8398. //    addEwpn(fbx,y,z,ewFireball,0,d->wdp,0);
  8399. //    addEwpn(fbx,y,z,ewFireball,0,d->wdp,down+1);
  8400.         addEwpn(fbx,y,z,wpn,2,wdp,up,getUID());
  8401.         addEwpn(fbx,y,z,wpn,2,wdp,8,getUID());
  8402.         addEwpn(fbx,y,z,wpn,2,wdp,down,getUID());
  8403.         Backend::sfx->play(wpnsfx(wpn),int(x));
  8404.     }
  8405.    
  8406.     if(clk3<-80 && !(rand()&63))
  8407.     {
  8408.         clk3=32;
  8409.     }
  8410.    
  8411.     if(!((clk4+1)&63))
  8412.     {
  8413.         int d2=(rand()%3)+1;
  8414.        
  8415.         if(d2>=left)
  8416.         {
  8417.             dir=d2;
  8418.         }
  8419.        
  8420.         if(dmisc1)
  8421.         {
  8422.             if(x<=40)
  8423.             {
  8424.                 dir=right;
  8425.             }
  8426.            
  8427.             if(x>=104)
  8428.             {
  8429.                 dir=left;
  8430.             }
  8431.         }
  8432.         else
  8433.         {
  8434.             if(x<=136)
  8435.             {
  8436.                 dir=right;
  8437.             }
  8438.            
  8439.             if(x>=200)
  8440.             {
  8441.                 dir=left;
  8442.             }
  8443.         }
  8444.     }
  8445.    
  8446.     if(clk4>=-1 && !((clk4+1)&7))
  8447.     {
  8448.         if(dir==left)
  8449.         {
  8450.             x-=1;
  8451.         }
  8452.         else
  8453.         {
  8454.             x+=1;
  8455.         }
  8456.     }
  8457.    
  8458.     clk4=(clk4+1)%256;
  8459.    
  8460.     return enemy::animate(index);
  8461. }
  8462.  
  8463. void eAquamentus::draw(BITMAP *dest)
  8464. {
  8465.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  8466.     {
  8467.         xofs=(dmisc1?-16:0);
  8468.         tile=o_tile+((clk&24)>>2)+(clk3>-32?(clk3>0?40:80):0);
  8469.        
  8470.         if(dying)
  8471.         {
  8472.             xofs=0;
  8473.             enemy::draw(dest);
  8474.         }
  8475.         else
  8476.         {
  8477.             drawblock(dest,15);
  8478.         }
  8479.     }
  8480.     else
  8481.     {
  8482.         int xblockofs=((dmisc1)?-16:16);
  8483.         xofs=0;
  8484.        
  8485.         if(clk<0 || dying)
  8486.         {
  8487.             enemy::draw(dest);
  8488.             return;
  8489.         }
  8490.        
  8491.         // face (0=firing, 2=resting)
  8492.         tile=o_tile+((clk3>0)?0:2);
  8493.         enemy::draw(dest);
  8494.         // tail (
  8495.         tile=o_tile+((clk&16)?1:3);
  8496.         xofs=xblockofs;
  8497.         enemy::draw(dest);
  8498.         // body
  8499.         yofs+=16;
  8500.         xofs=0;
  8501.         tile=o_tile+((clk&16)?20:22);
  8502.         enemy::draw(dest);
  8503.         xofs=xblockofs;
  8504.         tile=o_tile+((clk&16)?21:23);
  8505.         enemy::draw(dest);
  8506.         yofs-=16;
  8507.     }
  8508. }
  8509.  
  8510. bool eAquamentus::hit(weapon *w)
  8511. {
  8512.     if(!(w->scriptcoldet&1)) return false;
  8513.    
  8514.     switch(w->id)
  8515.     {
  8516.     case wBeam:
  8517.     case wRefBeam:
  8518.     case wMagic:
  8519.         hysz=32;
  8520.     }
  8521.    
  8522.     bool ret = (dying || hclk>0) ? false : sprite::hit(w);
  8523.     hysz=16;
  8524.     return ret;
  8525.    
  8526. }
  8527.  
  8528. eGohma::eGohma(fix X,fix Y,int Id,int Clk) : enemy((fix)128,(fix)48,Id,0)
  8529. {
  8530.     //these are here to bypass compiler warnings about unused arguments
  8531.     X=X;
  8532.     Y=Y;
  8533.     Clk=Clk;
  8534.    
  8535.     hxofs=-16;
  8536.     hxsz=48;
  8537.     clk4=0;
  8538.     yofs=playing_field_offset+1;
  8539.     dir=rand()%3+1;
  8540.    
  8541.     //nets+5340;
  8542. }
  8543.  
  8544. bool eGohma::animate(int index)
  8545. {
  8546.     if(dying)
  8547.         return Dead(index);
  8548.        
  8549.     if(clk==0)
  8550.     {
  8551.         removearmos(x,y);
  8552.     }
  8553.    
  8554.     // Movement clk must be separate from animation clk because of the Clock item
  8555.     if(!watch)
  8556.         clk4++;
  8557.        
  8558.     if((clk4&63)==0)
  8559.     {
  8560.         if(clk4&64)
  8561.             dir^=1;
  8562.         else
  8563.             dir=rand()%3+1;
  8564.     }
  8565.    
  8566.     if((clk&63)==3)
  8567.     {
  8568.         switch(dmisc1)
  8569.         {
  8570.         case 1:
  8571.             addEwpn(x,y+2,z,wpn,3,wdp,left,getUID());
  8572.             addEwpn(x,y+2,z,wpn,3,wdp,8,getUID());
  8573.             addEwpn(x,y+2,z,wpn,3,wdp,right,getUID());
  8574.             Backend::sfx->play(wpnsfx(wpn),int(x));
  8575.             break;
  8576.            
  8577.         default:
  8578.             if(dmisc1 != 1 && dmisc1 != 2)
  8579.             {
  8580.                 addEwpn(x,y+2,z,wpn,3,wdp,8,getUID());
  8581.                 Backend::sfx->play(wpnsfx(wpn),int(x));
  8582.                 Backend::sfx->play(wpnsfx(wpn),int(x));
  8583.             }
  8584.            
  8585.             break;
  8586.         }
  8587.     }
  8588.    
  8589.     if((dmisc1 == 2)&& clk3>=16 && clk3<116)
  8590.     {
  8591.         if(!(clk3%8))
  8592.         {
  8593.             FireBreath(true);
  8594.         }
  8595.     }
  8596.    
  8597.     if(clk4&1)
  8598.         move((fix)1);
  8599.        
  8600.     if(++clk3>=400)
  8601.         clk3=0;
  8602.        
  8603.     return enemy::animate(index);
  8604. }
  8605.  
  8606. void eGohma::draw(BITMAP *dest)
  8607. {
  8608.     tile=o_tile;
  8609.    
  8610.     if(clk<0 || dying)
  8611.     {
  8612.         enemy::draw(dest);
  8613.         return;
  8614.     }
  8615.    
  8616.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  8617.     {
  8618.         // left side
  8619.         xofs=-16;
  8620.         flip=0;
  8621.         //      if(clk&16) tile=180;
  8622.         //      else { tile=182; flip=1; }
  8623.         tile+=(3*((clk&48)>>4));
  8624.         enemy::draw(dest);
  8625.        
  8626.         // right side
  8627.         xofs=16;
  8628.         //      tile=(180+182)-tile;
  8629.         tile=o_tile;
  8630.         tile+=(3*((clk&48)>>4))+2;
  8631.         enemy::draw(dest);
  8632.        
  8633.         // body
  8634.         xofs=0;
  8635.         tile=o_tile;
  8636.        
  8637.         //      tile+=(3*((clk&24)>>3))+2;
  8638.         if(clk3<16)
  8639.             tile+=7;
  8640.         else if(clk3<116)
  8641.             tile+=10;
  8642.         else if(clk3<132)
  8643.             tile+=7;
  8644.         else
  8645.             tile+=((clk3-132)&24)?4:1;
  8646.            
  8647.         enemy::draw(dest);
  8648.        
  8649.     }
  8650.     else
  8651.     {
  8652.         // left side
  8653.         xofs=-16;
  8654.         flip=0;
  8655.        
  8656.         if(!(clk&16))
  8657.         {
  8658.             tile+=2;
  8659.             flip=1;
  8660.         }
  8661.        
  8662.         enemy::draw(dest);
  8663.        
  8664.         // right side
  8665.         tile=o_tile;
  8666.         xofs=16;
  8667.        
  8668.         if((clk&16)) tile+=2;
  8669.        
  8670.         //      tile=(180+182)-tile;
  8671.         enemy::draw(dest);
  8672.        
  8673.         // body
  8674.         tile=o_tile;
  8675.         xofs=0;
  8676.        
  8677.         if(clk3<16)
  8678.             tile+=4;
  8679.         else if(clk3<116)
  8680.             tile+=5;
  8681.         else if(clk3<132)
  8682.             tile+=4;
  8683.         else tile+=((clk3-132)&8)?3:1;
  8684.        
  8685.         enemy::draw(dest);
  8686.        
  8687.     }
  8688. }
  8689.  
  8690. int eGohma::takehit(weapon *w)
  8691. {
  8692.     int wpnId = w->id;
  8693.     int power = w->power;
  8694.     int wpnx = w->x;
  8695.     int wpnDir = w->dir;
  8696.     int def = defenditemclass(wpnId, &power, w);
  8697.    
  8698.     if(def < 0)
  8699.     {
  8700.         if(!((wpnDir==up || wpnDir==l_up || wpnDir==r_up) && abs(int(x)-wpnx)<=8 && clk3>=16 && clk3<116))
  8701.         {
  8702.             Backend::sfx->play(WAV_CHINK,int(x));
  8703.             return 1;
  8704.         }
  8705.     }
  8706.    
  8707.     return enemy::takehit(w);
  8708. }
  8709.  
  8710. eLilDig::eLilDig(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  8711. {
  8712.     count_enemy=(id==(id&0xFFF));
  8713.     //nets+4360+(((id&0xFF)-eDIGPUP2)*40);
  8714. }
  8715.  
  8716. bool eLilDig::animate(int index)
  8717. {
  8718.     if(dying)
  8719.         return Dead(index);
  8720.        
  8721.     if(clk==0)
  8722.     {
  8723.         removearmos(x,y);
  8724.     }
  8725.    
  8726.     if(misc<=128)
  8727.     {
  8728.         if(!(++misc&31))
  8729.             step+=0.25;
  8730.     }
  8731.    
  8732.     variable_walk_8(rate,homing,hrate,spw_floater);
  8733.     return enemy::animate(index);
  8734. }
  8735.  
  8736. void eLilDig::draw(BITMAP *dest)
  8737. {
  8738.     tile = o_tile;
  8739.     //    tile = 160;
  8740.     int fdiv = frate/4;
  8741.     int efrate = fdiv == 0 ? 0 : clk/fdiv;
  8742.     int f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
  8743.            efrate:((clk>=(frate>>1))?1:0);
  8744.            
  8745.            
  8746.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  8747.     {
  8748.         switch(dir-8)                                           //directions get screwed up after 8.  *shrug*
  8749.         {
  8750.         case up:                                              //u
  8751.             flip=0;
  8752.             break;
  8753.            
  8754.         case l_up:                                            //d
  8755.             flip=0;
  8756.             tile+=4;
  8757.             break;
  8758.            
  8759.         case l_down:                                          //l
  8760.             flip=0;
  8761.             tile+=8;
  8762.             break;
  8763.            
  8764.         case left:                                            //r
  8765.             flip=0;
  8766.             tile+=12;
  8767.             break;
  8768.            
  8769.         case r_down:                                          //ul
  8770.             flip=0;
  8771.             tile+=20;
  8772.             break;
  8773.            
  8774.         case down:                                            //ur
  8775.             flip=0;
  8776.             tile+=24;
  8777.             break;
  8778.            
  8779.         case r_up:                                            //dl
  8780.             flip=0;
  8781.             tile+=28;
  8782.             break;
  8783.            
  8784.         case right:                                           //dr
  8785.             flip=0;
  8786.             tile+=32;
  8787.             break;
  8788.         }
  8789.        
  8790.         tile+=f2;
  8791.     }
  8792.     else
  8793.     {
  8794.         tile+=(clk>=6)?1:0;
  8795.     }
  8796.    
  8797.     enemy::draw(dest);
  8798. }
  8799.  
  8800. eBigDig::eBigDig(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  8801. {
  8802.     superman=1;
  8803.     hxofs=hyofs=-8;
  8804.     hxsz=hysz=32;
  8805.     hzsz=16; // hard to jump.
  8806. }
  8807.  
  8808. bool eBigDig::animate(int index)
  8809. {
  8810.     if(dying)
  8811.         return Dead(index);
  8812.        
  8813.     if(clk==0)
  8814.     {
  8815.         removearmos(x,y);
  8816.     }
  8817.    
  8818.     switch(misc)
  8819.     {
  8820.     case 0:
  8821.         variable_walk_8(rate,homing,hrate,spw_floater,-8,-16,23,23);
  8822.         break;
  8823.        
  8824.     case 1:
  8825.         ++misc;
  8826.         break;
  8827.        
  8828.     case 2:
  8829.         for(int i=0; i<dmisc5; i++)
  8830.         {
  8831.             addenemy(x,y,dmisc1+0x1000,-15);
  8832.         }
  8833.        
  8834.         for(int i=0; i<dmisc6; i++)
  8835.         {
  8836.             addenemy(x,y,dmisc2+0x1000,-15);
  8837.         }
  8838.        
  8839.         for(int i=0; i<dmisc7; i++)
  8840.         {
  8841.             addenemy(x,y,dmisc3+0x1000,-15);
  8842.         }
  8843.        
  8844.         for(int i=0; i<dmisc8; i++)
  8845.         {
  8846.             addenemy(x,y,dmisc4+0x1000,-15);
  8847.         }
  8848.        
  8849.         if(itemguy) // Hand down the carried item
  8850.         {
  8851.             guycarryingitem = guys.Count()-1;
  8852.             ((enemy*)guys.spr(guycarryingitem))->itemguy = true;
  8853.             itemguy = false;
  8854.         }
  8855.        
  8856.         stop_bgsfx(index);
  8857.        
  8858.         if(deadsfx > 0) Backend::sfx->play(deadsfx,int(x));
  8859.        
  8860.         return true;
  8861.     }
  8862.    
  8863.     return enemy::animate(index);
  8864. }
  8865.  
  8866. void eBigDig::draw(BITMAP *dest)
  8867. {
  8868.     if(anim!=aDIG)
  8869.     {
  8870.         update_enemy_frame();
  8871.         xofs-=8;
  8872.         yofs-=8;
  8873.         drawblock(dest,15);
  8874.         xofs+=8;
  8875.         yofs+=8;
  8876.         return;
  8877.     }
  8878.    
  8879.     tile = o_tile;
  8880.     int fdiv = frate/4;
  8881.     int efrate = fdiv == 0 ? 0 : clk/fdiv;
  8882.    
  8883.     int f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
  8884.            efrate:((clk>=(frate>>1))?1:0);
  8885.            
  8886.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  8887.     {
  8888.         switch(dir-8)                                           //directions get screwed up after 8.  *shrug*
  8889.         {
  8890.         case up:                                              //u
  8891.             flip=0;
  8892.             break;
  8893.            
  8894.         case l_up:                                            //d
  8895.             flip=0;
  8896.             tile+=8;
  8897.             break;
  8898.            
  8899.         case l_down:                                          //l
  8900.             flip=0;
  8901.             tile+=40;
  8902.             break;
  8903.            
  8904.         case left:                                            //r
  8905.             flip=0;
  8906.             tile+=48;
  8907.             break;
  8908.            
  8909.         case r_down:                                          //ul
  8910.             flip=0;
  8911.             tile+=80;
  8912.             break;
  8913.            
  8914.         case down:                                            //ur
  8915.             flip=0;
  8916.             tile+=88;
  8917.            
  8918.             break;
  8919.            
  8920.         case r_up:                                            //dl
  8921.             flip=0;
  8922.             tile+=120;
  8923.             break;
  8924.            
  8925.         case right:                                           //dr
  8926.             flip=0;
  8927.             tile+=128;
  8928.             break;
  8929.         }
  8930.        
  8931.         tile+=(f2*2);
  8932.     }
  8933.     else
  8934.     {
  8935.         tile+=(f2)?0:2;
  8936.         flip=(clk&1)?1:0;
  8937.     }
  8938.    
  8939.     xofs-=8;
  8940.     yofs-=8;
  8941.     drawblock(dest,15);
  8942.     xofs+=8;
  8943.     yofs+=8;
  8944. }
  8945.  
  8946. int eBigDig::takehit(weapon *w)
  8947. {
  8948.     int wpnId = w->id;
  8949.    
  8950.     if(wpnId==wWhistle && misc==0)
  8951.         misc=1;
  8952.        
  8953.     return 0;
  8954. }
  8955.  
  8956. eGanon::eGanon(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  8957. {
  8958.     hxofs=hyofs=8;
  8959.     hzsz=16; //can't be jumped.
  8960.     clk2=70;
  8961.     misc=-1;
  8962.     mainguy=!getmapflag();
  8963. }
  8964.  
  8965. bool eGanon::animate(int index)
  8966. {
  8967.     if(dying)
  8968.    
  8969.         return Dead(index);
  8970.        
  8971.     if(clk==0)
  8972.     {
  8973.         removearmos(x,y);
  8974.     }
  8975.    
  8976.     switch(misc)
  8977.     {
  8978.     case -1:
  8979.         misc=0;
  8980.        
  8981.     case 0:
  8982.         if(++clk2>72 && !(rand()&3))
  8983.         {
  8984.             addEwpn(x,y,z,wpn,3,wdp,dir,getUID());
  8985.             Backend::sfx->play(wpnsfx(wpn),int(x));
  8986.             clk2=0;
  8987.         }
  8988.        
  8989.         Stunclk=0;
  8990.         constant_walk(rate,homing,spw_none);
  8991.         break;
  8992.        
  8993.     case 1:
  8994.     case 2:
  8995.         if(--Stunclk<=0)
  8996.         {
  8997.             int r=rand();
  8998.            
  8999.             if(r&1)
  9000.             {
  9001.                 y=96;
  9002.                
  9003.                 if(r&2)
  9004.                     x=160;
  9005.                 else
  9006.                     x=48;
  9007.                    
  9008.                 if(tooclose(x,y,48))
  9009.                     x=208-x;
  9010.             }
  9011.            
  9012.             loadpalset(csBOSS,pSprite(d->bosspal));
  9013.             misc=0;
  9014.         }
  9015.        
  9016.         break;
  9017.        
  9018.     case 3:
  9019.         if(hclk>0)
  9020.             break;
  9021.            
  9022.         misc=4;
  9023.         clk=0;
  9024.         hxofs=1000;
  9025.         loadpalset(9,pSprite(spPILE));
  9026.         music_stop();
  9027.         Backend::sfx->stop(WAV_ROAR);
  9028.        
  9029.         if(deadsfx>0) Backend::sfx->play(deadsfx,int(x));
  9030.        
  9031.         Backend::sfx->play(WAV_GANON,128);
  9032.         items.add(new item(x+8,y+8,(fix)0,iPile,ipDUMMY,0));
  9033.         break;
  9034.        
  9035.     case 4:
  9036.         if(clk>=80)
  9037.         {
  9038.             misc=5;
  9039.            
  9040.             if(getmapflag())
  9041.             {
  9042.                 game->lvlitems[dlevel]|=liBOSS;
  9043.                 //play_DmapMusic();
  9044.                 playLevelMusic();
  9045.                 return true;
  9046.             }
  9047.            
  9048.             Backend::sfx->play(WAV_CLEARED,128);
  9049.             items.add(new item(x+8,y+8,(fix)0,iBigTri,ipBIGTRI,0));
  9050.             setmapflag();
  9051.         }
  9052.        
  9053.         break;
  9054.     }
  9055.    
  9056.     return enemy::animate(index);
  9057. }
  9058.  
  9059.  
  9060. int eGanon::takehit(weapon *w)
  9061. {
  9062.     //these are here to bypass compiler warnings about unused arguments
  9063.     int wpnId = w->id;
  9064.     int power = w->power;
  9065.     int enemyHitWeapon = w->parentitem;
  9066.    
  9067.     switch(misc)
  9068.     {
  9069.     case 0:
  9070.         if(wpnId!=wSword)
  9071.             return 0;
  9072.            
  9073.         hp-=power;
  9074.        
  9075.         if(hp>0)
  9076.         {
  9077.             misc=1;
  9078.             Stunclk=64;
  9079.         }
  9080.         else
  9081.         {
  9082.             loadpalset(csBOSS,pSprite(spBROWN));
  9083.             misc=2;
  9084.             Stunclk=284;
  9085.             hp=guysbuf[id&0xFFF].hp;                              //16*DAMAGE_MULTIPLIER;
  9086.         }
  9087.        
  9088.         Backend::sfx->play(WAV_EHIT,int(x));
  9089.        
  9090.         if(hitsfx>0) Backend::sfx->play(hitsfx,int(x));
  9091.        
  9092.         return 1;
  9093.        
  9094.     case 2:
  9095.         if(wpnId!=wArrow || (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_arrow))<4)
  9096.             return 0;
  9097.            
  9098.         misc=3;
  9099.         hclk=81;
  9100.         loadpalset(9,pSprite(spBROWN));
  9101.         return 1;
  9102.     }
  9103.    
  9104.     return 0;
  9105. }
  9106.  
  9107. void eGanon::draw(BITMAP *dest)
  9108. {
  9109.     switch(misc)
  9110.     {
  9111.     case 0:
  9112.         if((clk&3)==3)
  9113.             tile=(rand()%5)*2+o_tile;
  9114.            
  9115.         if(db!=999)
  9116.             break;
  9117.            
  9118.     case 2:
  9119.         if(Stunclk<64 && (Stunclk&1))
  9120.             break;
  9121.            
  9122.     case -1:
  9123.         tile=o_tile;
  9124.        
  9125.         //fall through
  9126.     case 1:
  9127.     case 3:
  9128.         drawblock(dest,15);
  9129.         break;
  9130.        
  9131.     case 4:
  9132.         draw_guts(dest);
  9133.         draw_flash(dest);
  9134.         break;
  9135.     }
  9136. }
  9137.  
  9138. void eGanon::draw_guts(BITMAP *dest)
  9139. {
  9140.     int c = zc_min(clk>>3,8);
  9141.     tile = clk<24 ? 74 : 75;
  9142.     overtile16(dest,tile,x+8,y+c+playing_field_offset,9,0);
  9143.     overtile16(dest,tile,x+8,y+16-c+playing_field_offset,9,0);
  9144.     overtile16(dest,tile,x+c,y+8+playing_field_offset,9,0);
  9145.     overtile16(dest,tile,x+16-c,y+8+playing_field_offset,9,0);
  9146.     overtile16(dest,tile,x+c,y+c+playing_field_offset,9,0);
  9147.     overtile16(dest,tile,x+16-c,y+c+playing_field_offset,9,0);
  9148.     overtile16(dest,tile,x+c,y+16-c+playing_field_offset,9,0);
  9149.     overtile16(dest,tile,x+16-c,y+16-c+playing_field_offset,9,0);
  9150. }
  9151.  
  9152. void eGanon::draw_flash(BITMAP *dest)
  9153. {
  9154.  
  9155.     int c = clk-(clk>>2);
  9156.     cs = (frame&3)+6;
  9157.     overtile16(dest,194,x+8,y+8-clk+playing_field_offset,cs,0);
  9158.     overtile16(dest,194,x+8,y+8+clk+playing_field_offset,cs,2);
  9159.     overtile16(dest,195,x+8-clk,y+8+playing_field_offset,cs,0);
  9160.     overtile16(dest,195,x+8+clk,y+8+playing_field_offset,cs,1);
  9161.     overtile16(dest,196,x+8-c,y+8-c+playing_field_offset,cs,0);
  9162.     overtile16(dest,196,x+8+c,y+8-c+playing_field_offset,cs,1);
  9163.     overtile16(dest,196,x+8-c,y+8+c+playing_field_offset,cs,2);
  9164.     overtile16(dest,196,x+8+c,y+8+c+playing_field_offset,cs,3);
  9165. }
  9166.  
  9167. void getBigTri(int id2)
  9168. {
  9169.     /*
  9170.       *************************
  9171.       * BIG TRIFORCE SEQUENCE *
  9172.       *************************
  9173.       0 BIGTRI out, WHITE flash in
  9174.       4 WHITE flash out, PILE cset white
  9175.       8 WHITE in
  9176.       ...
  9177.       188 WHITE out
  9178.       191 PILE cset red
  9179.       200 top SHUTTER opens
  9180.       209 bottom SHUTTER opens
  9181.       */
  9182.     Backend::sfx->play(itemsbuf[id2].playsound,128);
  9183.     guys.clear();
  9184.    
  9185.     if(itemsbuf[id2].flags & ITEM_GAMEDATA)
  9186.     {
  9187.         game->lvlitems[dlevel]|=liTRIFORCE;
  9188.     }
  9189.    
  9190.     draw_screen(tmpscr);
  9191.    
  9192.     for(int f=0; f<24*8 && !Quit; f++)
  9193.     {
  9194.         if(f==4)
  9195.         {
  9196.             for(int i=1; i<16; i++)
  9197.             {
  9198.                 RAMpal[CSET(9)+i]=_RGB(63,63,63);
  9199.             }
  9200.         }
  9201.        
  9202.         if((f&7)==0)
  9203.         {
  9204.             for(int cs=2; cs<5; cs++)
  9205.             {
  9206.                 for(int i=1; i<16; i++)
  9207.                 {
  9208.                     RAMpal[CSET(cs)+i]=_RGB(63,63,63);
  9209.                 }
  9210.             }
  9211.            
  9212.             refreshpal=true;
  9213.         }
  9214.        
  9215.         if((f&7)==4)
  9216.         {
  9217.             if(currscr<128) loadlvlpal(DMaps[currdmap].color);
  9218.             else loadlvlpal(0xB);
  9219.         }
  9220.        
  9221.         if(f==191)
  9222.         {
  9223.             loadpalset(9,pSprite(spPILE));
  9224.         }
  9225.        
  9226.         advanceframe(true);
  9227.     }
  9228.    
  9229.     //play_DmapMusic();
  9230.     playLevelMusic();
  9231.    
  9232.     if(itemsbuf[id2].flags & ITEM_FLAG1 && currscr < 128)
  9233.     {
  9234.         Link.dowarp(1,0); //side warp
  9235.     }
  9236. }
  9237.  
  9238. /**********************************/
  9239. /***  Multiple-Segment Enemies  ***/
  9240. /**********************************/
  9241.  
  9242. eMoldorm::eMoldorm(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  9243. {
  9244.     x=128;
  9245.     y=48;
  9246.     dir=(rand()&7)+8;
  9247.     superman=1;
  9248.     fading=fade_invisible;
  9249.     hxofs=1000;
  9250.     segcnt=clk;
  9251.     segid=Id|0x1000;
  9252.     clk=0;
  9253.     id=guys.Count();
  9254.     yofs=playing_field_offset;
  9255.     tile=o_tile;
  9256.     /*
  9257.       if (get_bit(quest_rules,qr_NEWENEMYTILES))
  9258.       {
  9259.         tile=nets+1220;
  9260.       }
  9261.       else
  9262.       {
  9263.         tile=57;
  9264.       }
  9265.     */
  9266. }
  9267.  
  9268. bool eMoldorm::animate(int index)
  9269. {
  9270.  
  9271.     if(clk==0)
  9272.     {
  9273.         removearmos(x,y);
  9274.     }
  9275.    
  9276.     if(clk2)
  9277.     {
  9278.         if(--clk2 == 0)
  9279.         {
  9280.             if(flags&guy_neverret)
  9281.                 never_return(index);
  9282.                
  9283.             if(!dmisc2)
  9284.                 leave_item();
  9285.                
  9286.             stop_bgsfx(index);
  9287.             return true;
  9288.         }
  9289.     }
  9290.     else
  9291.     {
  9292.         if(stunclk>0)
  9293.             stunclk=0;
  9294.         constant_walk_8(rate,homing,spw_floater);
  9295.         misc=dir;
  9296.        
  9297.         // If any higher-numbered segments were killed, segcnt can be too high,
  9298.         // leading to a crash
  9299.         if(index+segcnt>=guys.Count())
  9300.             segcnt=guys.Count()-index-1;
  9301.        
  9302.         for(int i=index+1; i<index+segcnt+1; i++)
  9303.         {
  9304.             enemy* segment=((enemy*)guys.spr(i));
  9305.            
  9306.             // More validation - if segcnt was wrong, this may not
  9307.             // actually be a Moldorm segment
  9308.             if(segment->id!=segid)
  9309.             {
  9310.                 segcnt=i-index-1;
  9311.                 break;
  9312.             }
  9313.            
  9314.             if(i==index+1)
  9315.             {
  9316.                 x=segment->x;
  9317.                 y=segment->y;
  9318.             }
  9319.            
  9320.             segment->o_tile=tile;
  9321.            
  9322.             if((i==index+segcnt)&&(i!=index+1))                   //tail
  9323.             {
  9324.                 segment->dummy_int[1]=2;
  9325.             }
  9326.             else
  9327.             {
  9328.                 segment->dummy_int[1]=1;
  9329.             }
  9330.            
  9331.             if(i==index+1)                                        //head
  9332.             {
  9333.                 segment->dummy_int[1]=0;
  9334.             }
  9335.            
  9336.             if(segment->hp <= 0)
  9337.             {
  9338.                 int offset=1;
  9339.                
  9340.                 for(int j=i; j<index+segcnt; j++)
  9341.                 {
  9342.                     // Triple-check
  9343.                     if(((enemy*)guys.spr(j+1))->id!=segid)
  9344.                     {
  9345.                         segcnt=j-index+1; // Add 1 because of --segcnt below
  9346.                         break;
  9347.                     }
  9348.                     zc_swap(((enemy*)guys.spr(j))->hp,((enemy*)guys.spr(j+1))->hp);
  9349.                     zc_swap(((enemy*)guys.spr(j))->hclk,((enemy*)guys.spr(j+1))->hclk);
  9350.                 }
  9351.                
  9352.                 segment->hclk=33;
  9353.                 --segcnt;
  9354.                 --i; // Recheck the same index in case multiple segments died at once
  9355.             }
  9356.         }
  9357.        
  9358.         if(segcnt==0)
  9359.         {
  9360.             clk2=19;
  9361.            
  9362.             x=guys.spr(index+1)->x;
  9363.             y=guys.spr(index+1)->y;
  9364.         }
  9365.     }
  9366.    
  9367.     return false;
  9368. }
  9369.  
  9370. esMoldorm::esMoldorm(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  9371. {
  9372.     x=128;
  9373.     y=48;
  9374.     yofs=playing_field_offset;
  9375.     hyofs=4;
  9376.     hxsz=hysz=8;
  9377.     hxofs=1000;
  9378.     mainguy=count_enemy=false;
  9379.     parentclk = 0;
  9380.     bgsfx=-1;
  9381.     flags&=~guy_neverret;
  9382.     //deadsfx = WAV_EDEAD;
  9383. }
  9384.  
  9385. bool esMoldorm::animate(int index)
  9386. {
  9387.     // Shouldn't be possible, but better to be sure
  9388.     if(index==0)
  9389.         dying=true;
  9390.    
  9391.     if(dying)
  9392.     {
  9393.         if(!dmisc2)
  9394.             item_set=0;
  9395.            
  9396.         return Dead(index);
  9397.     }
  9398.    
  9399.     if(clk>=0)
  9400.     {
  9401.         hxofs=4;
  9402.         step=((enemy*)guys.spr(index-1))->step;
  9403.        
  9404.         if(parentclk == 0)
  9405.         {
  9406.             misc=dir;
  9407.             dir=((enemy*)guys.spr(index-1))->misc;
  9408.             //do alignment, as in parent's animation :-/ -DD
  9409.             x.v&=0xFFFF0000;
  9410.             y.v&=0xFFFF0000;
  9411.         }
  9412.        
  9413.         parentclk=(parentclk+1)%((int)(8.0/step));
  9414.        
  9415.         if(!watch)
  9416.         {
  9417.             sprite::move(step);
  9418.         }
  9419.     }
  9420.    
  9421.     return enemy::animate(index);
  9422. }
  9423.  
  9424. int esMoldorm::takehit(weapon *w)
  9425. {
  9426.     if(enemy::takehit(w))
  9427.         return (w->id==wSBomb) ? 1 : 2;                         // force it to wait a frame before checking sword attacks again
  9428.        
  9429.     return 0;
  9430. }
  9431.  
  9432. void esMoldorm::draw(BITMAP *dest)
  9433. {
  9434.     tile=o_tile;
  9435.     int fdiv = frate/4;
  9436.     int efrate = fdiv == 0 ? 0 : clk/fdiv;
  9437.    
  9438.     int f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
  9439.            efrate:((clk>=(frate>>1))?1:0);
  9440.            
  9441.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  9442.     {
  9443.         tile+=dummy_int[1]*40;
  9444.        
  9445.         if(dir<8)
  9446.         {
  9447.             flip=0;
  9448.             tile+=4*zc_max(dir, 0); // dir is -1 if trapped
  9449.            
  9450.             if(dir>3) // Skip to the next row for diagonals
  9451.                 tile+=4;
  9452.         }
  9453.         else
  9454.         {
  9455.             switch(dir-8)                                           //directions get screwed up after 8.  *shrug*
  9456.             {
  9457.             case up:                                              //u
  9458.                 flip=0;
  9459.                 break;
  9460.                
  9461.             case l_up:                                            //d
  9462.                 flip=0;
  9463.                 tile+=4;
  9464.                 break;
  9465.                
  9466.             case l_down:                                          //l
  9467.                 flip=0;
  9468.                 tile+=8;
  9469.                 break;
  9470.                
  9471.             case left:                                            //r
  9472.                 flip=0;
  9473.                 tile+=12;
  9474.                 break;
  9475.                
  9476.             case r_down:                                          //ul
  9477.                 flip=0;
  9478.                 tile+=20;
  9479.                 break;
  9480.                
  9481.             case down:                                            //ur
  9482.                 flip=0;
  9483.                 tile+=24;
  9484.                 break;
  9485.                
  9486.             case r_up:                                            //dl
  9487.                 flip=0;
  9488.                 tile+=28;
  9489.                 break;
  9490.                
  9491.             case right:                                           //dr
  9492.                 flip=0;
  9493.                 tile+=32;
  9494.                 break;
  9495.             }
  9496.         }
  9497.        
  9498.         tile+=f2;
  9499.     }
  9500.    
  9501.     if(clk>=0)
  9502.         enemy::draw(dest);
  9503. }
  9504.  
  9505. eLanmola::eLanmola(fix X,fix Y,int Id,int Clk) : eBaseLanmola(X,Y,Id,Clk)
  9506. {
  9507.     x=64;
  9508.     y=80;
  9509.     dir=up;
  9510.     superman=1;
  9511.     fading=fade_invisible;
  9512.     hxofs=1000;
  9513.     segcnt=clk;
  9514.     clk=0;
  9515.    
  9516.     //set up move history
  9517.     for(int i=0; i <= (1<<dmisc2); i++)
  9518.         prevState.push_back(std::pair<std::pair<fix, fix>, int>(std::pair<fix,fix>(x,y), dir));
  9519. }
  9520.  
  9521. bool eLanmola::animate(int index)
  9522. {
  9523.     if(clk==0)
  9524.     {
  9525.         removearmos(x,y);
  9526.     }
  9527.    
  9528.     if(clk2)
  9529.     {
  9530.         if(--clk2 == 0)
  9531.         {
  9532.             if(!dmisc3)
  9533.                 leave_item();
  9534.                
  9535.             stop_bgsfx(index);
  9536.             return true;
  9537.         }
  9538.        
  9539.         return false;
  9540.     }
  9541.    
  9542.    
  9543.     //this animation style plays ALL KINDS of havoc on the Lanmola segments, since it causes
  9544.     //the direction AND x,y position of the lanmola to vary in uncertain ways.
  9545.     //I've added a complete movement history to this enemy to compensate -DD
  9546.     constant_walk(rate,homing,spw_none);
  9547.     prevState.pop_front();
  9548.     prevState.push_front(std::pair<std::pair<fix, fix>, int>(std::pair<fix, fix>(x,y), dir));
  9549.    
  9550.     // This could cause a crash with Moldorms. I didn't see the same problem
  9551.     // with Lanmolas, but it looks like it ought to be possible, so here's
  9552.     // the same solution. - Saf
  9553.     if(index+segcnt>=guys.Count())
  9554.         segcnt=guys.Count()-index-1;
  9555.    
  9556.     for(int i=index+1; i<index+segcnt+1; i++)
  9557.     {
  9558.         enemy* segment=((enemy*)guys.spr(i));
  9559.        
  9560.         // More validation in case segcnt is wrong
  9561.         if((segment->id&0xFFF)!=(id&0xFFF))
  9562.         {
  9563.             segcnt=i-index-1;
  9564.             break;
  9565.         }
  9566.        
  9567.         segment->o_tile=o_tile;
  9568.        
  9569.         if((i==index+segcnt)&&(i!=index+1))
  9570.         {
  9571.             segment->dummy_int[1]=1;                //tail
  9572.         }
  9573.         else
  9574.         {
  9575.             segment->dummy_int[1]=0;
  9576.         }
  9577.        
  9578.         if(segment->hp <= 0)
  9579.         {
  9580.             for(int j=i; j<index+segcnt; j++)
  9581.             {
  9582.                 // Triple-check
  9583.                 if((((enemy*)guys.spr(j+1))->id&0xFFF)!=(id&0xFFF))
  9584.                 {
  9585.                     segcnt=j-index+1; // Add 1 because of --segcnt below
  9586.                     break;
  9587.                 }
  9588.                 zc_swap(((enemy*)guys.spr(j))->hp,((enemy*)guys.spr(j+1))->hp);
  9589.                 zc_swap(((enemy*)guys.spr(j))->hclk,((enemy*)guys.spr(j+1))->hclk);
  9590.             }
  9591.            
  9592.             ((enemy*)guys.spr(i))->hclk=33;
  9593.             --segcnt;
  9594.             --i; // Recheck the same index in case multiple segments died at once
  9595.         }
  9596.     }
  9597.    
  9598.     if(segcnt==0)
  9599.     {
  9600.         clk2=19;
  9601.         x=guys.spr(index+1)->x;
  9602.         y=guys.spr(index+1)->y;
  9603.         setmapflag(mTMPNORET);
  9604.     }
  9605.    
  9606.     //this enemy is invincible.. BUT scripts don't know that, and can "kill" it by setting the hp negative.
  9607.     //which is... disastrous.
  9608.     hp = 1;
  9609.     return enemy::animate(index);
  9610. }
  9611.  
  9612. esLanmola::esLanmola(fix X,fix Y,int Id,int Clk) : eBaseLanmola(X,Y,Id,Clk)
  9613. {
  9614.     x=64;
  9615.     y=80;
  9616.     hxofs=1000;
  9617.     hxsz=8;
  9618.     mainguy=false;
  9619.     count_enemy=(id<0x2000)?true:false;
  9620.    
  9621.     //set up move history
  9622.     for(int i=0; i <= (1<<dmisc2); i++)
  9623.         prevState.push_back(std::pair<std::pair<fix, fix>, int>(std::pair<fix,fix>(x,y), dir));
  9624.        
  9625.     bgsfx = -1;
  9626.     flags&=~guy_neverret;
  9627. }
  9628.  
  9629. bool esLanmola::animate(int index)
  9630. {
  9631.     // Shouldn't be possible, but who knows
  9632.     if(index==0)
  9633.         dying=true;
  9634.    
  9635.     if(dying)
  9636.     {
  9637.         xofs=0;
  9638.        
  9639.         if(!dmisc3)
  9640.             item_set=0;
  9641.            
  9642.         return Dead(index);
  9643.     }
  9644.    
  9645.     if(clk>=0)
  9646.     {
  9647.         hxofs=4;
  9648.        
  9649.         if(!watch)
  9650.         {
  9651.             std::pair<std::pair<fix, fix>, int> newstate = ((eBaseLanmola*)guys.spr(index-1))->prevState.front();
  9652.             prevState.pop_front();
  9653.             prevState.push_back(newstate);
  9654.             x = newstate.first.first;
  9655.             y = newstate.first.second;
  9656.             dir = newstate.second;
  9657.         }
  9658.     }
  9659.    
  9660.     return enemy::animate(index);
  9661. }
  9662.  
  9663. int esLanmola::takehit(weapon *w)
  9664. {
  9665.     if(enemy::takehit(w))
  9666.         return (w->id==wSBomb) ? 1 : 2;                         // force it to wait a frame before checking sword attacks again
  9667.        
  9668.     return 0;
  9669. }
  9670.  
  9671. void esLanmola::draw(BITMAP *dest)
  9672. {
  9673.     tile=o_tile;
  9674.     int fdiv = frate/4;
  9675.     int efrate = fdiv == 0 ? 0 : clk/fdiv;
  9676.    
  9677.     int f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
  9678.            efrate:((clk>=(frate>>1))?1:0);
  9679.            
  9680.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  9681.     {
  9682.         if(id>=0x2000)
  9683.         {
  9684.             tile+=20;
  9685.            
  9686.             if(dummy_int[1]==1)
  9687.             {
  9688.                 tile+=20;
  9689.             }
  9690.         }
  9691.        
  9692.         switch(dir)
  9693.         {
  9694.         case up:
  9695.             flip=0;
  9696.             break;
  9697.            
  9698.         case down:
  9699.             flip=0;
  9700.             tile+=4;
  9701.             break;
  9702.            
  9703.         case left:
  9704.             flip=0;
  9705.             tile+=8;
  9706.             break;
  9707.            
  9708.         case right:
  9709.             flip=0;
  9710.             tile+=12;
  9711.             break;
  9712.         }
  9713.        
  9714.         tile+=f2;
  9715.     }
  9716.     else
  9717.     {
  9718.         if(id>=0x2000)
  9719.         {
  9720.             tile+=1;
  9721.         }
  9722.     }
  9723.    
  9724.     if(clk>=0)
  9725.         enemy::draw(dest);
  9726. }
  9727.  
  9728. eManhandla::eManhandla(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,0)
  9729. {
  9730.     //these are here to bypass compiler warnings about unused arguments
  9731.     Clk=Clk;
  9732.    
  9733.     superman=1;
  9734.     dir=(rand()&7)+8;
  9735.     armcnt=dmisc2?8:4;//((id==eMANHAN)?4:8);
  9736.    
  9737.     for(int i=0; i<armcnt; i++)
  9738.         arm[i]=i;
  9739.        
  9740.     fading=fade_blue_poof;
  9741.     //nets+4680;
  9742.     adjusted=false;
  9743. }
  9744.  
  9745. bool eManhandla::animate(int index)
  9746. {
  9747.     if(dying)
  9748.         return Dead(index);
  9749.        
  9750.     if(clk==0)
  9751.     {
  9752.         removearmos(x,y);
  9753.     }
  9754.    
  9755.    
  9756.     // check arm status, move dead ones to end of group
  9757.     for(int i=0; i<armcnt; i++)
  9758.     {
  9759.         if(!adjusted)
  9760.         {
  9761.             if(!dmisc2)
  9762.             {
  9763.                 ((enemy*)guys.spr(index+i+1))->o_tile=o_tile+40;
  9764.             }
  9765.             else
  9766.             {
  9767.                 ((enemy*)guys.spr(index+i+1))->o_tile=o_tile+160;
  9768.             }
  9769.         }
  9770.        
  9771.         if(((enemy*)guys.spr(index+i+1))->dying)
  9772.         {
  9773.             for(int j=i; j<armcnt-1; j++)
  9774.             {
  9775.                 zc_swap(arm[j],arm[j+1]);
  9776.                 guys.swap(index+j+1,index+j+2);
  9777.                
  9778.             }
  9779.            
  9780.             --armcnt;
  9781.         }
  9782.     }
  9783.    
  9784.     adjusted=true;
  9785.    
  9786.     // move or die
  9787.     if(armcnt==0)
  9788.         hp=0;
  9789.     else
  9790.     {
  9791.         // Speed starts at 0.5, and increases by 0.5 for each head lost. Max speed is 4.5.
  9792.         step=zc_min(4.5,(((!dmisc2)?4:8)-armcnt)*0.5+(dstep/100.0));
  9793.         int dx1=0, dy1=-8, dx2=15, dy2=15;
  9794.        
  9795.         if(!dmisc2)
  9796.         {
  9797.             for(int i=0; i<armcnt; i++)
  9798.             {
  9799.                 switch(arm[i])
  9800.                 {
  9801.                 case 0:
  9802.                     dy1=-24;
  9803.                     break;
  9804.                    
  9805.                 case 1:
  9806.                     dy2=31;
  9807.                     break;
  9808.                    
  9809.                 case 2:
  9810.                     dx1=-16;
  9811.                     break;
  9812.                    
  9813.                 case 3:
  9814.                     dx2=31;
  9815.                     break;
  9816.                 }
  9817.             }
  9818.         }
  9819.         else
  9820.         {
  9821.             dx1=-8, dy1=-16, dx2=23, dy2=23;
  9822.            
  9823.             for(int i=0; i<armcnt; i++)
  9824.             {
  9825.                 switch(arm[i]&3)
  9826.                 {
  9827.                 case 0:
  9828.                     dy1=-32;
  9829.                     break;
  9830.                    
  9831.                 case 1:
  9832.                     dy2=39;
  9833.                     break;
  9834.                    
  9835.                 case 2:
  9836.                     dx1=-24;
  9837.                     break;
  9838.                    
  9839.                 case 3:
  9840.                     dx2=39;
  9841.                     break;
  9842.                 }
  9843.             }
  9844.         }
  9845.        
  9846.         variable_walk_8(rate,homing,hrate,spw_floater,dx1,dy1,dx2,dy2);
  9847.        
  9848.         for(int i=0; i<armcnt; i++)
  9849.         {
  9850.             fix dx=(fix)0,dy=(fix)0;
  9851.            
  9852.             if(!dmisc2)
  9853.             {
  9854.                 switch(arm[i])
  9855.                 {
  9856.                 case 0:
  9857.                     dy=-16;
  9858.                     break;
  9859.                    
  9860.                 case 1:
  9861.                     dy=16;
  9862.                     break;
  9863.                    
  9864.                 case 2:
  9865.                     dx=-16;
  9866.                     break;
  9867.                    
  9868.                 case 3:
  9869.                     dx=16;
  9870.                     break;
  9871.                 }
  9872.             }
  9873.             else
  9874.             {
  9875.                 switch(arm[i])
  9876.                 {
  9877.                 case 0:
  9878.                     dy=-24;
  9879.                     dx=-8;
  9880.                     break;
  9881.                    
  9882.                 case 1:
  9883.                     dy=24;
  9884.                     dx=8;
  9885.                     break;
  9886.                    
  9887.                 case 2:
  9888.                     dx=-24;
  9889.                     dy=8;
  9890.                     break;
  9891.                    
  9892.                 case 3:
  9893.                     dx=24;
  9894.                     dy=-8;
  9895.                     break;
  9896.                    
  9897.                 case 4:
  9898.                     dy=-24;
  9899.                     dx=8;
  9900.                     break;
  9901.                    
  9902.                 case 5:
  9903.                     dy=24;
  9904.                     dx=-8;
  9905.                     break;
  9906.                    
  9907.                 case 6:
  9908.                     dx=-24;
  9909.                     dy=-8;
  9910.                     break;
  9911.                    
  9912.                 case 7:
  9913.                     dx=24;
  9914.                     dy=8;
  9915.                     break;
  9916.                 }
  9917.             }
  9918.            
  9919.             guys.spr(index+i+1)->x = x+dx;
  9920.             guys.spr(index+i+1)->y = y+dy;
  9921.         }
  9922.     }
  9923.    
  9924.     return enemy::animate(index);
  9925. }
  9926.  
  9927.  
  9928. int eManhandla::takehit(weapon *w)
  9929. {
  9930.     int wpnId = w->id;
  9931.    
  9932.     if(dying)
  9933.         return 0;
  9934.        
  9935.     switch(wpnId)
  9936.     {
  9937.     case wLitBomb:
  9938.     case wLitSBomb:
  9939.     case wBait:
  9940.     case wWhistle:
  9941.     case wFire:
  9942.     case wWind:
  9943.     case wSSparkle:
  9944.     case wFSparkle:
  9945.     case wPhantom:
  9946.         return 0;
  9947.        
  9948.     case wHookshot:
  9949.     case wBrang:
  9950.         Backend::sfx->play(WAV_CHINK,int(x));
  9951.         break;
  9952.        
  9953.     default:
  9954.         Backend::sfx->play(WAV_EHIT,int(x));
  9955.        
  9956.     }
  9957.    
  9958.     return 1;
  9959. }
  9960.  
  9961. void eManhandla::draw(BITMAP *dest)
  9962. {
  9963.     tile=o_tile;
  9964.     int fdiv = frate/4;
  9965.     int efrate = fdiv == 0 ? 0 : clk/fdiv;
  9966.    
  9967.     int f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
  9968.            efrate:((clk>=(frate>>1))?1:0);
  9969.            
  9970.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  9971.     {
  9972.         if(!dmisc2)
  9973.         {
  9974.             switch(dir-8)                                         //directions get screwed up after 8.  *shrug*
  9975.             {
  9976.             case up:                                            //u
  9977.                 flip=0;
  9978.                 break;
  9979.                
  9980.             case l_up:                                          //d
  9981.                 flip=0;
  9982.                 tile+=4;
  9983.                 break;
  9984.                
  9985.             case l_down:                                        //l
  9986.                 flip=0;
  9987.                 tile+=8;
  9988.                 break;
  9989.                
  9990.             case left:                                          //r
  9991.                 flip=0;
  9992.                 tile+=12;
  9993.                 break;
  9994.                
  9995.             case r_down:                                        //ul
  9996.                 flip=0;
  9997.                 tile+=20;
  9998.                 break;
  9999.                
  10000.             case down:                                          //ur
  10001.                 flip=0;
  10002.                 tile+=24;
  10003.                 break;
  10004.                
  10005.             case r_up:                                          //dl
  10006.                 flip=0;
  10007.                 tile+=28;
  10008.                 break;
  10009.                
  10010.             case right:                                         //dr
  10011.                 flip=0;
  10012.                 tile+=32;
  10013.                 break;
  10014.             }
  10015.            
  10016.             tile+=f2;
  10017.             enemy::draw(dest);
  10018.         }                                                       //manhandla 2, big body
  10019.         else
  10020.         {
  10021.        
  10022.             switch(dir-8)                                         //directions get screwed up after 8.  *shrug*
  10023.             {
  10024.             case up:                                            //u
  10025.                 flip=0;
  10026.                 break;
  10027.                
  10028.             case l_up:                                          //d
  10029.                 flip=0;
  10030.                 tile+=8;
  10031.                 break;
  10032.                
  10033.             case l_down:                                        //l
  10034.                 flip=0;
  10035.                 tile+=40;
  10036.                 break;
  10037.                
  10038.             case left:                                          //r
  10039.                 flip=0;
  10040.                 tile+=48;
  10041.                 break;
  10042.                
  10043.             case r_down:                                        //ul
  10044.                 flip=0;
  10045.                 tile+=80;
  10046.                 break;
  10047.                
  10048.             case down:                                          //ur
  10049.                 flip=0;
  10050.                 tile+=88;
  10051.                 break;
  10052.                
  10053.             case r_up:                                          //dl
  10054.                 flip=0;
  10055.                 tile+=120;
  10056.                 break;
  10057.                
  10058.             case right:                                         //dr
  10059.                 flip=0;
  10060.                 tile+=128;
  10061.                 break;
  10062.             }
  10063.            
  10064.             tile+=(f2*2);
  10065.             xofs-=8;
  10066.             yofs-=8;
  10067.             drawblock(dest,15);
  10068.             xofs+=8;
  10069.             yofs+=8;
  10070.         }
  10071.     }
  10072.     else
  10073.     {
  10074.         if(!dmisc2)
  10075.         {
  10076.             enemy::draw(dest);
  10077.         }
  10078.         else
  10079.         {
  10080.             xofs-=8;
  10081.             yofs-=8;
  10082.             enemy::draw(dest);
  10083.             xofs+=16;
  10084.             enemy::draw(dest);
  10085.             yofs+=16;
  10086.             enemy::draw(dest);
  10087.             xofs-=16;
  10088.             enemy::draw(dest);
  10089.             xofs+=8;
  10090.             yofs-=8;
  10091.         }
  10092.     }
  10093. }
  10094.  
  10095. esManhandla::esManhandla(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  10096. {
  10097.     id=misc=clk;
  10098.    
  10099.     dir = clk & 3;
  10100.     clk=0;
  10101.     mainguy=count_enemy=false;
  10102.     dummy_bool[0]=false;
  10103.     item_set=0;
  10104.     bgsfx=-1;
  10105.     deadsfx = WAV_EDEAD;
  10106.     flags &= (~guy_neverret);
  10107. }
  10108.  
  10109. bool esManhandla::animate(int index)
  10110.  
  10111. {
  10112.     if(dying)
  10113.         return Dead(index);
  10114.        
  10115.     if(clk==0)
  10116.     {
  10117.         removearmos(x,y);
  10118.     }
  10119.    
  10120.     if(--clk2<=0)
  10121.     {
  10122.         clk2=unsigned(rand())%5+5;
  10123.         clk3^=1;
  10124.     }
  10125.    
  10126.     if(!(rand()&127))
  10127.     {
  10128.         addEwpn(x,y,z,wpn,3,wdp,dir,getUID());
  10129.         Backend::sfx->play(wpnsfx(wpn),int(x));
  10130.     }
  10131.    
  10132.     return enemy::animate(index);
  10133. }
  10134.  
  10135. void esManhandla::draw(BITMAP *dest)
  10136. {
  10137.     tile=o_tile;
  10138.     int fdiv = frate/4;
  10139.     int efrate = fdiv == 0 ? 0 : clk/fdiv;
  10140.     int f2=get_bit(quest_rules,qr_NEWENEMYTILES)?
  10141.            efrate:((clk>=(frate>>1))?1:0);
  10142.            
  10143.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  10144.     {
  10145.         switch(misc&3)
  10146.         {
  10147.         case up:
  10148.             break;
  10149.            
  10150.         case down:
  10151.             tile+=4;
  10152.             break;
  10153.            
  10154.         case left:
  10155.             tile+=8;
  10156.             break;
  10157.            
  10158.         case right:
  10159.             tile+=12;
  10160.             break;
  10161.         }
  10162.        
  10163.         tile+=f2;
  10164.     }
  10165.     else
  10166.     {
  10167.         switch(misc&3)
  10168.         {
  10169.         case down:
  10170.             flip=2;
  10171.            
  10172.         case up:
  10173.             tile=(clk3)?188:189;
  10174.             break;
  10175.            
  10176.         case right:
  10177.             flip=1;
  10178.            
  10179.         case left:
  10180.             tile=(clk3)?186:187;
  10181.             break;
  10182.         }
  10183.     }
  10184.    
  10185.     enemy::draw(dest);
  10186. }
  10187.  
  10188. eGleeok::eGleeok(fix,fix,int Id,int Clk) : enemy((fix)120,(fix)48,Id,Clk)
  10189. {
  10190.     hzsz = 32; // can't be jumped.
  10191.     flameclk=0;
  10192.     misc=clk;                                                 // total head count
  10193.     clk3=clk;                                                 // live head count
  10194.     clk=0;
  10195.     clk2=60;                                                  // fire ball clock
  10196.     //    hp=(guysbuf[eGLEEOK2+(misc-2)].misc2)*(misc-1)*DAMAGE_MULTIPLIER+guysbuf[eGLEEOK2+(misc-2)].hp;
  10197.     hp=(guysbuf[id&0xFFF].misc2)*(misc-1)*DAMAGE_MULTIPLIER+guysbuf[id&0xFFF].hp;
  10198.     dir = down;
  10199.     hxofs=4;
  10200.     hxsz=8;
  10201.     //    frate=17*4;
  10202.     fading=fade_blue_poof;
  10203.    
  10204.     //nets+5420;
  10205.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  10206.     {
  10207.         /*
  10208.             necktile=o_tile+8;
  10209.             if (dmisc3)
  10210.             {
  10211.               necktile+=8;
  10212.             }
  10213.         */
  10214.         necktile=o_tile+dmisc6;
  10215.     }
  10216.     else
  10217.     {
  10218.         necktile=s_tile;
  10219.     }
  10220. }
  10221.  
  10222. bool eGleeok::animate(int index)
  10223. {
  10224.     if(dying)
  10225.         return Dead(index);
  10226.        
  10227.     if(clk==0)
  10228.     {
  10229.         removearmos(x,y);
  10230.     }
  10231.    
  10232.     // Check if a head was killed somehow...
  10233.     if(index+1+clk3>=guys.Count())
  10234.         clk3=guys.Count()-index-1;
  10235.     if(index+1+misc>=guys.Count())
  10236.         misc=guys.Count()-index-1;
  10237.    
  10238.     //fix for the "kill all enemies" item
  10239.     if(hp==-1000)
  10240.     {
  10241.         for(int i=0; i<clk3; ++i)
  10242.         {
  10243.             // I haven't seen this fail, but it seems like it ought to be
  10244.             // possible, so I'm checking for it. - Saf
  10245.             if((((enemy*)guys.spr(index+i+1))->id&0xFFF)!=(id&0xFFF))
  10246.                 break;
  10247.             ((enemy*)guys.spr(index+i+1))->hp=1;                   // re-animate each head,
  10248.             ((enemy*)guys.spr(index+i+1))->misc = -1;              // disconnect it,
  10249.             ((enemy*)guys.spr(index+i+1))->animate(index+i+1);     // let it animate one frame,
  10250.             ((enemy*)guys.spr(index+i+1))->hp=-1000;               // and kill it for good
  10251.         }
  10252.        
  10253.         clk3=0;
  10254.        
  10255.         for(int i=0; i<misc; i++)
  10256.         {
  10257.             if((((enemy*)guys.spr(index+i+1))->id&0xFFF)!=(id&0xFFF))
  10258.                 break;
  10259.             ((enemy*)guys.spr(index+i+1))->misc = -2;             // give the signal to disappear
  10260.         }
  10261.     }
  10262.    
  10263.     for(int i=0; i<clk3; i++)
  10264.     {
  10265.         enemy *head = ((enemy*)guys.spr(index+i+1));
  10266.         head->dummy_int[1]=necktile;
  10267.        
  10268.         if(get_bit(quest_rules,qr_NEWENEMYTILES))
  10269.         {
  10270.             head->dummy_int[2]=o_tile+dmisc8; //connected head tile
  10271.             head->dummy_int[3]=o_tile+dmisc9; //flying head tile
  10272.         }
  10273.         else
  10274.         {
  10275.             head->dummy_int[2]=necktile+1; //connected head tile
  10276.             head->dummy_int[3]=necktile+2; //flying head tile
  10277.         }
  10278.        
  10279.         head->dmisc5=dmisc5; //neck segments
  10280.        
  10281.         /*
  10282.             if (dmisc3)
  10283.             {
  10284.               head->dummy_bool[0]=true;
  10285.             }
  10286.         */
  10287.         if(head->hclk)
  10288.         {
  10289.             if(hclk==0)
  10290.             {
  10291.                 hp -= 1000 - head->hp;
  10292.                 hclk = 33;
  10293.                
  10294.                 if(hitsfx>0) Backend::sfx->play(hitsfx,int(head->x));
  10295.                
  10296.                 Backend::sfx->play(WAV_EHIT,int(head->x));
  10297.             }
  10298.            
  10299.             head->hclk = 0;
  10300.         }
  10301.        
  10302.         // Must be set in case of naughty ZScripts
  10303.         head->hp = 1000;
  10304.     }
  10305.    
  10306.     if(hp<=(guysbuf[id&0xFFF].misc2)*(clk3-1)*DAMAGE_MULTIPLIER)
  10307.     {
  10308.         ((enemy*)guys.spr(index+clk3))->misc = -1;              // give signal to fly off
  10309.         hp=(guysbuf[id&0xFFF].misc2)*(--clk3)*DAMAGE_MULTIPLIER;
  10310.     }
  10311.    
  10312.     if(!dmisc3)
  10313.     {
  10314.         if(++clk2>72 && !(rand()&3))
  10315.         {
  10316.             int i=rand()%misc;
  10317.             enemy *head = ((enemy*)guys.spr(index+i+1));
  10318.             addEwpn(head->x,head->y,head->z,wpn,3,wdp,dir,getUID());
  10319.             Backend::sfx->play(wpnsfx(wpn),int(x));
  10320.             clk2=0;
  10321.         }
  10322.     }
  10323.     else
  10324.     {
  10325.         if(++clk2>100 && !(rand()&3))
  10326.         {
  10327.             enemy *head = ((enemy*)guys.spr(rand()%misc+index+1));
  10328.             head->timer=rand()%50+50;
  10329.             clk2=0;
  10330.         }
  10331.     }
  10332.    
  10333.     if(hp<=0)
  10334.     {
  10335.         for(int i=0; i<misc; i++)
  10336.             ((enemy*)guys.spr(index+i+1))->misc = -2;             // give the signal to disappear
  10337.            
  10338.         if(flags&guy_neverret) never_return(index);
  10339.     }
  10340.    
  10341.     return enemy::animate(index);
  10342. }
  10343.  
  10344. int eGleeok::takehit(weapon*)
  10345. {
  10346.     return 0;
  10347. }
  10348.  
  10349. void eGleeok::draw(BITMAP *dest)
  10350. {
  10351.     tile=o_tile;
  10352.    
  10353.     if(dying)
  10354.     {
  10355.         enemy::draw(dest);
  10356.         return;
  10357.     }
  10358.    
  10359.     int f=clk/17;
  10360.    
  10361.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  10362.     {
  10363.         // body
  10364.         xofs=-8;
  10365.         yofs=32;
  10366.        
  10367.         switch(f)
  10368.        
  10369.         {
  10370.         case 0:
  10371.             tile+=0;
  10372.             break;
  10373.            
  10374.         case 1:
  10375.             tile+=2;
  10376.             break;
  10377.            
  10378.         case 2:
  10379.             tile+=4;
  10380.             break;
  10381.            
  10382.         default:
  10383.             tile+=6;
  10384.             break;
  10385.         }
  10386.     }
  10387.     else
  10388.     {
  10389.         // body
  10390.         xofs=-8;
  10391.         yofs=32;
  10392.        
  10393.         switch(f)
  10394.         {
  10395.         case 0:
  10396.             tile+=0;
  10397.             break;
  10398.            
  10399.         case 2:
  10400.             tile+=4;
  10401.             break;
  10402.            
  10403.         default:
  10404.             tile+=2;
  10405.             break;
  10406.         }
  10407.     }
  10408.    
  10409.     enemy::drawblock(dest,15);
  10410. }
  10411.  
  10412. void eGleeok::draw2(BITMAP *dest)
  10413. {
  10414.     // the neck stub
  10415.     tile=necktile;
  10416.     xofs=0;
  10417.     yofs=playing_field_offset;
  10418.    
  10419.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  10420.     {
  10421.         tile+=((clk&24)>>3);
  10422.     }
  10423.    
  10424.     /*
  10425.       else
  10426.       {
  10427.         tile=145;
  10428.       }
  10429.     */
  10430.     /*
  10431.       if(hp>0 && !dont_draw())
  10432.       sprite::draw(dest);
  10433.       */
  10434.     if(hp > 0 && !dont_draw())
  10435.     {
  10436.         if((tmpscr->flags3&fINVISROOM)&& !(current_item(itype_amulet)))
  10437.             sprite::drawcloaked(dest);
  10438.         else
  10439.             sprite::draw(dest);
  10440.     }
  10441. }
  10442.  
  10443. esGleeok::esGleeok(fix X,fix Y,int Id,int Clk, sprite * prnt) : enemy(X,Y,Id,Clk), parent(prnt)
  10444. {
  10445.     xoffset=0;
  10446.     yoffset=(fix)((dmisc5*4+2));
  10447. //  dummy_bool[0]=false;
  10448.     timer=0;
  10449.     /*  fixing */
  10450.     hp=1000;
  10451.     step=1;
  10452.     item_set=0;
  10453.     //x=120; y=70;
  10454.     x = xoffset+parent->x;
  10455.     y = yoffset+parent->y;
  10456.     hxofs=4;
  10457.     hxsz=8;
  10458.     yofs=playing_field_offset;
  10459.     clk2=clk;                                                 // how long to wait before moving first time
  10460.     clk=0;
  10461.     mainguy=count_enemy=false;
  10462.     dir=rand();
  10463.     clk3=((dir&2)>>1)+2;                                      // left or right
  10464.     dir&=1;                                                   // up or down
  10465.     dmisc5=vbound(dmisc5,1,255);
  10466.    
  10467.     for(int i=0; i<dmisc5; i++)
  10468.     {
  10469.         nxoffset[i] = 0;
  10470.         nyoffset[i] = 0;
  10471.         nx[i] = ((((i*(int)x) + (dmisc5-i)*((int)parent->x))) /dmisc5);
  10472.         ny[i] = ((((i*(int)y) + (dmisc5-i)*((int)parent->y))) /dmisc5);
  10473.     }
  10474.    
  10475.     necktile=0;
  10476.     //TODO compatibility? -DD
  10477.     /*
  10478.     for(int i=0; i<4; i++)
  10479.     {
  10480.       nx[i]=124;
  10481.       ny[i]=i*6+48;
  10482.     }*/
  10483.     bgsfx=-1;
  10484.     //no need for deadsfx
  10485. }
  10486.  
  10487. bool esGleeok::animate(int index)
  10488. {
  10489.     // don't call removearmos() - it's a segment.
  10490.    
  10491.     dmisc5=vbound(dmisc5,1,255);
  10492.    
  10493.     if(misc == 0)
  10494.     {
  10495.         x = (xoffset+parent->x);
  10496.         y = (yoffset+parent->y);
  10497.        
  10498.         for(int i=0; i<dmisc5; i++)
  10499.         {
  10500.             nx[i] = ((((i*(int)x) + (dmisc5-i)*((int)parent->x))) /dmisc5) + 3 + nxoffset[i];
  10501.             ny[i] = ((((i*(int)y) + (dmisc5-i)*((int)parent->y))) /dmisc5) + nyoffset[i];
  10502.         }
  10503.     }
  10504.    
  10505.     //  set up the head tiles
  10506. //  headtile=nets+5588;                                       //5580, actually.  must adjust for direction later on
  10507.     /*
  10508.       if (dummy_bool[0])                                        //if this is a flame gleeok
  10509.       {
  10510.         headtile+=180;
  10511.       }
  10512.     */
  10513.     headtile=dummy_int[2];                                       //5580, actually.  must adjust for direction later on
  10514.     flyingheadtile=dummy_int[3];
  10515.    
  10516.     //  set up the neck tiles
  10517.     necktile=dummy_int[1];
  10518.    
  10519.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  10520.     {
  10521.         necktile+=((clk&24)>>3);
  10522.     }
  10523.    
  10524.     /*
  10525.       else
  10526.       {
  10527.         necktile=145;
  10528.       }
  10529.     */
  10530.     //    ?((dummy_bool[0])?(nets+4052+(16+((clk&24)>>3))):(nets+4040+(8+((clk&24)>>3)))):145)
  10531.    
  10532.     switch(misc)
  10533.     {
  10534.     case 0:                                                 // live head
  10535.         //  set up the attached head tiles
  10536.         tile=headtile;
  10537.        
  10538.         if(get_bit(quest_rules,qr_NEWENEMYTILES))
  10539.         {
  10540.             tile+=((clk&24)>>3);
  10541.             /*
  10542.               if (dummy_bool[0]) {
  10543.               tile+=1561;
  10544.               }
  10545.               */
  10546.         }
  10547.        
  10548.         /*
  10549.             else
  10550.             {
  10551.               tile=146;
  10552.             }
  10553.         */
  10554.         if(++clk2>=0 && !(clk2&3))
  10555.         {
  10556.             if(y<= (int)parent->y + 8) dir=down;
  10557.            
  10558.             if(y>= (int)parent->y + dmisc5*8) dir = up;
  10559.            
  10560.             if(y<= (int)parent->y + 10 && !(rand()&31))
  10561.             {
  10562.                 dir^=1;
  10563.             }
  10564.            
  10565.             fix tempx = x;
  10566.             fix tempy = y;
  10567.            
  10568.             sprite::move(step);
  10569.             xoffset += (x-tempx);
  10570.             yoffset += (y-tempy);
  10571.            
  10572.             if(clk2>=4)
  10573.             {
  10574.                 clk3^=1;
  10575.                 clk2=-4;
  10576.             }
  10577.             else
  10578.             {
  10579.                 if(x <= (int)parent->x-(dmisc5*6))
  10580.                 {
  10581.                     clk3=right;
  10582.                 }
  10583.                
  10584.                 if(x >= (int)parent->x+(dmisc5*6))
  10585.                 {
  10586.                     clk3=left;
  10587.                 }
  10588.                
  10589.                 if(y <= (int)parent->y+(dmisc5*6) && !(rand()&15))
  10590.                 {
  10591.                     clk3^=1;                                        // x jig
  10592.                 }
  10593.                 else
  10594.                 {
  10595.                     if(y<=(int)parent->y+(dmisc5*4) && !(rand()&31))
  10596.                     {
  10597.                         clk3^=1;                                      // x switch back
  10598.                     }
  10599.                    
  10600.                     clk2=-4;
  10601.                 }
  10602.             }
  10603.            
  10604.             zc_swap(dir,clk3);
  10605.             tempx = x;
  10606.             tempy = y;
  10607.             sprite::move(step);
  10608.             xoffset += (x-tempx);
  10609.             yoffset += (y-tempy);
  10610.             zc_swap(dir,clk3);
  10611.            
  10612.             for(int i=1; i<dmisc5; i++)
  10613.             {
  10614.                 nxoffset[i] = (rand()%3);
  10615.                 nyoffset[i] = (rand()%3);
  10616.             }
  10617.         }
  10618.        
  10619.         break;
  10620.        
  10621.     case 1:                                                 // flying head
  10622.         if(clk>=0)
  10623.        
  10624.         {
  10625.             variable_walk_8(rate,homing,hrate,spw_floater);
  10626.         }
  10627.        
  10628.         break;
  10629.        
  10630.         // the following are messages sent from the main guy...
  10631.     case -1:                                                // got chopped off
  10632.     {
  10633.         misc=1;
  10634.         superman=1;
  10635.         hxofs=xofs=0;
  10636.         hxsz=16;
  10637.         cs=8;
  10638.         clk=-24;
  10639.         clk2=40;
  10640.         dir=(rand()&7)+8;
  10641.         step=8.0/9.0;
  10642.     }
  10643.     break;
  10644.    
  10645.     case -2:                                                // the big guy is dead
  10646.         return true;
  10647.     }
  10648.    
  10649.     if(timer)
  10650.     {
  10651.         if(!(timer%8))
  10652.         {
  10653.             FireBreath(true);
  10654.         }
  10655.        
  10656.         --timer;
  10657.     }
  10658.    
  10659.     return enemy::animate(index);
  10660. }
  10661.  
  10662. int esGleeok::takehit(weapon *w)
  10663. {
  10664.     int ret = enemy::takehit(w);
  10665.    
  10666.     if(ret==-1)
  10667.         return 2; // force it to wait a frame before checking sword attacks again
  10668.        
  10669.     return ret;
  10670. }
  10671.  
  10672. void esGleeok::draw(BITMAP *dest)
  10673. {
  10674.     dmisc5=vbound(dmisc5,1,255);
  10675.    
  10676.     switch(misc)
  10677.     {
  10678.     case 0:                                                 //neck
  10679.         if(!dont_draw())
  10680.         {
  10681.             for(int i=1; i<dmisc5; i++)                              //draw the neck
  10682.             {
  10683.                 if(get_bit(quest_rules,qr_NEWENEMYTILES))
  10684.                 {
  10685.                     if((tmpscr->flags3&fINVISROOM)&& !(current_item(itype_amulet)))
  10686.                         overtilecloaked16(dest,necktile+(i*dmisc7),nx[i]-4,ny[i]+playing_field_offset,0);
  10687.                     else
  10688.                         overtile16(dest,necktile+(i*dmisc7),nx[i]-4,ny[i]+playing_field_offset,cs,0);
  10689.                 }
  10690.                 else
  10691.                 {
  10692.                     if((tmpscr->flags3&fINVISROOM)&& !(current_item(itype_amulet)))
  10693.                         overtilecloaked16(dest,necktile,nx[i]-4,ny[i]+playing_field_offset,0);
  10694.                     else
  10695.                         overtile16(dest,necktile,nx[i]-4,ny[i]+playing_field_offset,cs,0);
  10696.                 }
  10697.             }
  10698.         }
  10699.        
  10700.         break;
  10701.        
  10702.     case 1:                                                 //flying head
  10703.         tile=flyingheadtile;
  10704.        
  10705.         if(get_bit(quest_rules,qr_NEWENEMYTILES))
  10706.         {
  10707.             tile+=((clk&24)>>3);
  10708.             break;
  10709.         }
  10710.        
  10711.         /*
  10712.             else
  10713.             {
  10714.               tile=(clk&1)?147:148;
  10715.               break;
  10716.             }
  10717.         */
  10718.     }
  10719. }
  10720.  
  10721. void esGleeok::draw2(BITMAP *dest)
  10722. {
  10723.     enemy::draw(dest);
  10724. }
  10725.  
  10726. ePatra::ePatra(fix ,fix ,int Id,int Clk) : enemy((fix)128,(fix)48,Id,Clk)
  10727. {
  10728.     adjusted=false;
  10729.     dir=(rand()&7)+8;
  10730.     //step=0.25;
  10731.     flycnt=dmisc1;
  10732.     flycnt2=dmisc2;
  10733.     loopcnt=0;
  10734.    
  10735.     if(dmisc6<short(1))dmisc6=1; // ratio cannot be 0!
  10736. }
  10737.  
  10738. bool ePatra::animate(int index)
  10739. {
  10740.     if(dying)
  10741.     {
  10742.         for(int i=index+1; i<index+flycnt+flycnt2+1; i++)
  10743.         {
  10744.             ((enemy*)guys.spr(i))->hp = -1000;
  10745.         }
  10746.        
  10747.         return Dead(index);
  10748.     }
  10749.    
  10750.     if(clk==0)
  10751.     {
  10752.         removearmos(x,y);
  10753.     }
  10754.    
  10755.     variable_walk_8(rate,homing,hrate,spw_floater);
  10756.    
  10757.     if(++clk2>84)
  10758.     {
  10759.         clk2=0;
  10760.        
  10761.         if(loopcnt)
  10762.             --loopcnt;
  10763.         else
  10764.         {
  10765.             if((misc%dmisc6)==0)
  10766.                 loopcnt=dmisc7;
  10767.         }
  10768.        
  10769.         ++misc;
  10770.     }
  10771.    
  10772.     double size=1;
  10773.    
  10774.     for(int i=index+1; i<index+flycnt+1; i++)
  10775.     {
  10776.         //outside ring
  10777.         if(!adjusted)
  10778.         {
  10779.             if(get_bit(quest_rules,qr_NEWENEMYTILES))
  10780.             {
  10781.                 ((enemy*)guys.spr(i))->o_tile=o_tile+dmisc8;
  10782.             }
  10783.             else
  10784.             {
  10785.                 ((enemy*)guys.spr(i))->o_tile=o_tile+1;
  10786.             }
  10787.            
  10788.             ((enemy*)guys.spr(i))->cs=dmisc9;
  10789.             ((enemy*)guys.spr(i))->hp=dmisc3;
  10790.         }
  10791.        
  10792.         if(((enemy*)guys.spr(i))->hp <= 0)
  10793.         {
  10794.             for(int j=i; j<index+flycnt+flycnt2; j++)
  10795.             {
  10796.                 guys.swap(j,j+1);
  10797.             }
  10798.            
  10799.             --flycnt;
  10800.         }
  10801.         else
  10802.         {
  10803.             int pos2 = ((enemy*)guys.spr(i))->misc;
  10804.             double a2 = (clk2-pos2*84.0/(dmisc1 == 0 ? 1 : dmisc1))*PI/42;
  10805.            
  10806.             if(!dmisc4)
  10807.             {
  10808.                 //maybe playing_field_offset here?
  10809.                 if(loopcnt>0)
  10810.                 {
  10811.                     guys.spr(i)->x =  cos(a2+PI/2)*56*size - sin(pos2*PI*2/(dmisc1 == 0 ? 1 : dmisc1))*28*size;
  10812.                     guys.spr(i)->y = -sin(a2+PI/2)*56*size + cos(pos2*PI*2/(dmisc1 == 0 ? 1 : dmisc1))*28*size;
  10813.                 }
  10814.                 else
  10815.                 {
  10816.                     guys.spr(i)->x =  cos(a2+PI/2)*28*size;
  10817.                     guys.spr(i)->y = -sin(a2+PI/2)*28*size;
  10818.                 }
  10819.                
  10820.                 temp_x=guys.spr(i)->x;
  10821.                 temp_y=guys.spr(i)->y;
  10822.             }
  10823.             else
  10824.             {
  10825.                 circle_x =  cos(a2+PI/2)*42;
  10826.                 circle_y = -sin(a2+PI/2)*42;
  10827.                
  10828.                 if(loopcnt>0)
  10829.                 {
  10830.                     guys.spr(i)->x =  cos(a2+PI/2)*42;
  10831.                     guys.spr(i)->y = (-sin(a2+PI/2)-cos(pos2*PI*2/(dmisc1 == 0 ? 1 : dmisc1)))*21;
  10832.                 }
  10833.                 else
  10834.                 {
  10835.                     guys.spr(i)->x = circle_x;
  10836.                     guys.spr(i)->y = circle_y;
  10837.                 }
  10838.                
  10839.                 temp_x=circle_x;
  10840.                 temp_y=circle_y;
  10841.             }
  10842.            
  10843.             double ddir=atan2(double(temp_y),double(temp_x));
  10844.            
  10845.             if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
  10846.             {
  10847.                 guys.spr(i)->dir=l_down;
  10848.             }
  10849.             else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
  10850.             {
  10851.                 guys.spr(i)->dir=left;
  10852.             }
  10853.             else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
  10854.             {
  10855.                 guys.spr(i)->dir=l_up;
  10856.             }
  10857.             else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
  10858.             {
  10859.                 guys.spr(i)->dir=up;
  10860.             }
  10861.             else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
  10862.             {
  10863.                 guys.spr(i)->dir=r_up;
  10864.             }
  10865.             else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
  10866.             {
  10867.                 guys.spr(i)->dir=right;
  10868.             }
  10869.             else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
  10870.             {
  10871.                 guys.spr(i)->dir=r_down;
  10872.             }
  10873.             else
  10874.             {
  10875.                 guys.spr(i)->dir=down;
  10876.             }
  10877.            
  10878.             guys.spr(i)->x += x;
  10879.             guys.spr(i)->y += y;
  10880.         }
  10881.     }
  10882.    
  10883.     if(dmisc5==1)
  10884.     {
  10885.         if(!(rand()&127))
  10886.         {
  10887.             addEwpn(x,y,z,wpn,3,wdp,dir,getUID());
  10888.             Backend::sfx->play(wpnsfx(wpn),int(x));
  10889.         }
  10890.     }
  10891.    
  10892.     size=.5;
  10893.    
  10894.     if(flycnt2)
  10895.     {
  10896.         for(int i=index+flycnt+1; i<index+flycnt+flycnt2+1; i++)//inner ring
  10897.         {
  10898.             if(!adjusted)
  10899.             {
  10900.                 ((enemy*)guys.spr(i))->hp=12*DAMAGE_MULTIPLIER;
  10901.                
  10902.                 if(get_bit(quest_rules,qr_NEWENEMYTILES))
  10903.                 {
  10904.                     switch(dmisc5)
  10905.                     {
  10906.                         // Center eye shoots projectiles; make room for its firing tiles
  10907.                     case 1:
  10908.                         ((enemy*)guys.spr(i))->o_tile=o_tile+120;
  10909.                         break;
  10910.                        
  10911.                         // Center eyes does not shoot; use tiles two rows below for inner eyes.
  10912.                     default:
  10913.                     case 2:
  10914.                         ((enemy*)guys.spr(i))->o_tile=o_tile+40;
  10915.                         break;
  10916.                     }
  10917.                 }
  10918.                 else
  10919.                 {
  10920.                     ((enemy*)guys.spr(i))->o_tile=o_tile+1;
  10921.                 }
  10922.                
  10923.                 ((enemy*)guys.spr(i))->cs=dmisc9;
  10924.             }
  10925.            
  10926.             if(flycnt>0)
  10927.             {
  10928.                 ((enemy*)guys.spr(i))->superman=true;
  10929.             }
  10930.             else
  10931.             {
  10932.                 ((enemy*)guys.spr(i))->superman=false;
  10933.             }
  10934.            
  10935.             if(((enemy*)guys.spr(i))->hp <= 0)
  10936.             {
  10937.                 for(int j=i; j<index+flycnt+flycnt2; j++)
  10938.                 {
  10939.                     guys.swap(j,j+1);
  10940.                 }
  10941.                
  10942.                 --flycnt2;
  10943.             }
  10944.             else
  10945.             {
  10946.                 if(dmisc5==2)
  10947.                 {
  10948.                     if(!(rand()&127))
  10949.                     {
  10950.                         addEwpn(guys.spr(i)->x,guys.spr(i)->y,guys.spr(i)->z,wpn,3,wdp,dir,getUID());
  10951.                         Backend::sfx->play(wpnsfx(wpn),int(x));
  10952.                     }
  10953.                 }
  10954.                
  10955.                 int pos2 = ((enemy*)guys.spr(i))->misc;
  10956.                 double a2 = ((clk2-pos2*84/(dmisc2==0 ? 1 : dmisc2))*PI/(42));
  10957.                
  10958.                 if(dmisc4==0)
  10959.                 {
  10960.                     if(loopcnt>0)
  10961.                     {
  10962.                         guys.spr(i)->x =  cos(a2+PI/2)*56*size - sin(pos2*PI*2/(dmisc2==0? 1 : dmisc2))*28*size;
  10963.                         guys.spr(i)->y = -sin(a2+PI/2)*56*size + cos(pos2*PI*2/(dmisc2==0?1:dmisc2))*28*size;
  10964.                     }
  10965.                     else
  10966.                     {
  10967.                         guys.spr(i)->x =  cos(a2+PI/2)*28*size;
  10968.                         guys.spr(i)->y = -sin(a2+PI/2)*28*size;
  10969.                     }
  10970.                    
  10971.                     temp_x=guys.spr(i)->x;
  10972.                     temp_y=guys.spr(i)->y;
  10973.                 }
  10974.                 else
  10975.                 {
  10976.                     circle_x =  cos(a2+PI/2)*42*size;
  10977.                     circle_y = -sin(a2+PI/2)*42*size;
  10978.                    
  10979.                     if(loopcnt>0)
  10980.                     {
  10981.                         guys.spr(i)->x =  cos(a2+PI/2)*42*size;
  10982.                         guys.spr(i)->y = (-sin(a2+PI/2)-cos(pos2*PI*2/(dmisc2 == 0 ? 1 : dmisc2)))*21*size;
  10983.                     }
  10984.                     else
  10985.                     {
  10986.                         guys.spr(i)->x = circle_x;
  10987.                         guys.spr(i)->y = circle_y;
  10988.                     }
  10989.                    
  10990.                     temp_x=circle_x;
  10991.                     temp_y=circle_y;
  10992.                 }
  10993.                
  10994.                 double ddir=atan2(double(temp_y),double(temp_x));
  10995.                
  10996.                 if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
  10997.                 {
  10998.                     guys.spr(i)->dir=l_down;
  10999.                 }
  11000.                 else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
  11001.                 {
  11002.                     guys.spr(i)->dir=left;
  11003.                 }
  11004.                 else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
  11005.                 {
  11006.                     guys.spr(i)->dir=l_up;
  11007.                 }
  11008.                 else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
  11009.                 {
  11010.                     guys.spr(i)->dir=up;
  11011.                 }
  11012.                 else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
  11013.                 {
  11014.                     guys.spr(i)->dir=r_up;
  11015.                 }
  11016.                 else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
  11017.                 {
  11018.                     guys.spr(i)->dir=right;
  11019.                 }
  11020.                 else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
  11021.                 {
  11022.                     guys.spr(i)->dir=r_down;
  11023.                 }
  11024.                 else
  11025.                 {
  11026.                     guys.spr(i)->dir=down;
  11027.                 }
  11028.                
  11029.                 guys.spr(i)->x += x;
  11030.                 guys.spr(i)->y = y-guys.spr(i)->y;
  11031.                
  11032.             }
  11033.         }
  11034.     }
  11035.    
  11036.     adjusted=true;
  11037.     return enemy::animate(index);
  11038. }
  11039.  
  11040. void ePatra::draw(BITMAP *dest)
  11041. {
  11042.     tile=o_tile;
  11043.     update_enemy_frame();
  11044.     enemy::draw(dest);
  11045. }
  11046.  
  11047. int ePatra::defend(int wpnId, int *power, int edef)
  11048. {
  11049.     int ret = enemy::defend(wpnId, power, edef);
  11050.    
  11051.     if(ret < 0 && (flycnt||flycnt2))
  11052.         return 0;
  11053.        
  11054.     return ret;
  11055. }
  11056.  
  11057. esPatra::esPatra(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  11058. {
  11059.     //cs=8;
  11060.     item_set=0;
  11061.     misc=clk;
  11062.     clk = -((misc*21)>>1)-1;
  11063.     yofs=playing_field_offset;
  11064.     hyofs=2;
  11065.     hxsz=hysz=12;
  11066.     hxofs=2;
  11067.     mainguy=count_enemy=false;
  11068.     bgsfx=-1;
  11069.     //o_tile=0;
  11070.     flags &= (~guy_neverret);
  11071.     deadsfx = WAV_EDEAD;
  11072.     hitsfx = WAV_EHIT;
  11073. }
  11074.  
  11075. bool esPatra::animate(int index)
  11076. {
  11077.     if(dying)
  11078.         return Dead(index);
  11079.        
  11080.     return enemy::animate(index);
  11081. }
  11082.  
  11083. void esPatra::draw(BITMAP *dest)
  11084. {
  11085.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  11086.     {
  11087.         tile = o_tile+(clk&3);
  11088.        
  11089.         switch(dir)                                             //directions get screwed up after 8.  *shrug*
  11090.         {
  11091.         case up:                                              //u
  11092.             flip=0;
  11093.             break;
  11094.            
  11095.         case down:                                            //d
  11096.             flip=0;
  11097.             tile+=4;
  11098.             break;
  11099.            
  11100.         case left:                                            //l
  11101.             flip=0;
  11102.             tile+=8;
  11103.             break;
  11104.            
  11105.         case right:                                           //r
  11106.             flip=0;
  11107.             tile+=12;
  11108.             break;
  11109.            
  11110.         case l_up:                                            //ul
  11111.             flip=0;
  11112.             tile+=20;
  11113.             break;
  11114.            
  11115.         case r_up:                                            //ur
  11116.             flip=0;
  11117.             tile+=24;
  11118.             break;
  11119.            
  11120.         case l_down:                                          //dl
  11121.             flip=0;
  11122.             tile+=28;
  11123.             break;
  11124.            
  11125.         case r_down:                                          //dr
  11126.             flip=0;
  11127.             tile+=32;
  11128.             break;
  11129.         }
  11130.     }
  11131.     else
  11132.     {
  11133.         tile = o_tile+((clk&2)>>1);
  11134.     }
  11135.    
  11136.     if(clk>=0)
  11137.         enemy::draw(dest);
  11138. }
  11139.  
  11140.  
  11141. ePatraBS::ePatraBS(fix ,fix ,int Id,int Clk) : enemy((fix)128,(fix)48,Id,Clk)
  11142. {
  11143.     adjusted=false;
  11144.     dir=(rand()&7)+8;
  11145.     step=0.25;
  11146.     //flycnt=6; flycnt2=0;
  11147.     flycnt=dmisc1;
  11148.     flycnt2=0; // PatraBS doesn't have inner rings!
  11149.     loopcnt=0;
  11150.     hxsz = 32;
  11151.     hxofs=-8;
  11152.    
  11153.     if(dmisc6<short(1))dmisc6=1; // ratio cannot be 0!
  11154.    
  11155.     //nets+4480;
  11156. }
  11157.  
  11158. bool ePatraBS::animate(int index)
  11159. {
  11160.     if(dying)
  11161.         return Dead(index);
  11162.        
  11163.     if(clk==0)
  11164.     {
  11165.         removearmos(x,y);
  11166.     }
  11167.    
  11168.     variable_walk_8(rate,homing,hrate,spw_floater);
  11169.    
  11170.     if(++clk2>90)
  11171.     {
  11172.         clk2=0;
  11173.        
  11174.         if(loopcnt)
  11175.             --loopcnt;
  11176.         else
  11177.         {
  11178.             if((misc%dmisc6)==0)
  11179.                 loopcnt=dmisc7;
  11180.         }
  11181.        
  11182.         ++misc;
  11183.     }
  11184.    
  11185.     //    double size=1;;
  11186.     for(int i=index+1; i<index+flycnt+1; i++)
  11187.     {
  11188.         if(!adjusted)
  11189.         {
  11190.             ((enemy*)guys.spr(i))->hp=dmisc3;
  11191.            
  11192.             if(get_bit(quest_rules,qr_NEWENEMYTILES))
  11193.             {
  11194.                 ((enemy*)guys.spr(i))->o_tile=o_tile+dmisc8;
  11195.             }
  11196.             else
  11197.             {
  11198.                 ((enemy*)guys.spr(i))->o_tile=o_tile+1;
  11199.             }
  11200.            
  11201.             ((enemy*)guys.spr(i))->cs = dmisc9;
  11202.         }
  11203.        
  11204.         if(((enemy*)guys.spr(i))->hp <= 0)
  11205.         {
  11206.             for(int j=i; j<index+flycnt+flycnt2; j++)
  11207.             {
  11208.                 guys.swap(j,j+1);
  11209.             }
  11210.            
  11211.             --flycnt;
  11212.         }
  11213.         else
  11214.         {
  11215.             int pos2 = ((enemy*)guys.spr(i))->misc;
  11216.             double a2 = (clk2-pos2*90/(dmisc1==0?1:dmisc1))*PI/45;
  11217.             temp_x =  cos(a2+PI/2)*45;
  11218.             temp_y = -sin(a2+PI/2)*45;
  11219.            
  11220.             if(loopcnt>0)
  11221.             {
  11222.                 guys.spr(i)->x =  cos(a2+PI/2)*45;
  11223.                 guys.spr(i)->y = (-sin(a2+PI/2)-cos(pos2*PI*2/(dmisc1==0?1:dmisc1)))*22.5;
  11224.             }
  11225.             else
  11226.             {
  11227.                 guys.spr(i)->x = temp_x;
  11228.                 guys.spr(i)->y = temp_y;
  11229.             }
  11230.            
  11231.             double ddir=atan2(double(temp_y),double(temp_x));
  11232.            
  11233.             if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
  11234.             {
  11235.                 guys.spr(i)->dir=l_down;
  11236.             }
  11237.             else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
  11238.             {
  11239.                 guys.spr(i)->dir=left;
  11240.             }
  11241.             else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
  11242.             {
  11243.                 guys.spr(i)->dir=l_up;
  11244.             }
  11245.             else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
  11246.             {
  11247.                 guys.spr(i)->dir=up;
  11248.             }
  11249.             else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
  11250.             {
  11251.                 guys.spr(i)->dir=r_up;
  11252.             }
  11253.             else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
  11254.             {
  11255.                 guys.spr(i)->dir=right;
  11256.             }
  11257.             else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
  11258.             {
  11259.                 guys.spr(i)->dir=r_down;
  11260.             }
  11261.             else
  11262.             {
  11263.                 guys.spr(i)->dir=down;
  11264.             }
  11265.            
  11266.             guys.spr(i)->x += x;
  11267.             guys.spr(i)->y += y;
  11268.         }
  11269.     }
  11270.    
  11271.     adjusted=true;
  11272.     return enemy::animate(index);
  11273. }
  11274.  
  11275. void ePatraBS::draw(BITMAP *dest)
  11276. {
  11277.     tile=o_tile;
  11278.    
  11279.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  11280.     {
  11281.         double ddir=atan2(double(y-(Link.y)),double(Link.x-x));
  11282.        
  11283.         if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8)))
  11284.         {
  11285.             lookat=l_down;
  11286.         }
  11287.         else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8)))
  11288.         {
  11289.             lookat=down;
  11290.         }
  11291.         else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8)))
  11292.         {
  11293.             lookat=r_down;
  11294.         }
  11295.         else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8)))
  11296.         {
  11297.             lookat=right;
  11298.         }
  11299.         else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8)))
  11300.         {
  11301.             lookat=r_up;
  11302.         }
  11303.         else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8)))
  11304.         {
  11305.             lookat=up;
  11306.         }
  11307.         else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8)))
  11308.         {
  11309.             lookat=l_up;
  11310.         }
  11311.         else
  11312.         {
  11313.             lookat=left;
  11314.         }
  11315.        
  11316.         switch(lookat)                                          //directions get screwed up after 8.  *shrug*
  11317.         {
  11318.         case up:                                              //u
  11319.             flip=0;
  11320.             break;
  11321.            
  11322.         case down:                                            //d
  11323.             flip=0;
  11324.             tile+=8;
  11325.             break;
  11326.            
  11327.         case left:                                            //l
  11328.             flip=0;
  11329.             tile+=40;
  11330.             break;
  11331.            
  11332.         case right:                                           //r
  11333.             flip=0;
  11334.             tile+=48;
  11335.             break;
  11336.            
  11337.         case l_up:                                            //ul
  11338.             flip=0;
  11339.             tile+=80;
  11340.             break;
  11341.            
  11342.         case r_up:                                            //ur
  11343.             flip=0;
  11344.             tile+=88;
  11345.             break;
  11346.            
  11347.         case l_down:                                          //dl
  11348.             flip=0;
  11349.             tile+=120;
  11350.             break;
  11351.            
  11352.         case r_down:                                          //dr
  11353.             flip=0;
  11354.             tile+=128;
  11355.             break;
  11356.         }
  11357.        
  11358.         tile+=(2*(clk&3));
  11359.         xofs-=8;
  11360.         yofs-=8;
  11361.         drawblock(dest,15);
  11362.         xofs+=8;
  11363.         yofs+=8;
  11364.     }
  11365.     else
  11366.     {
  11367.         flip=(clk&1);
  11368.         xofs-=8;
  11369.         yofs-=8;
  11370.         enemy::draw(dest);
  11371.         xofs+=16;
  11372.         enemy::draw(dest);
  11373.         yofs+=16;
  11374.         enemy::draw(dest);
  11375.         xofs-=16;
  11376.         enemy::draw(dest);
  11377.         xofs+=8;
  11378.         yofs-=8;
  11379.     }
  11380. }
  11381.  
  11382. int ePatraBS::defend(int wpnId, int *power, int edef)
  11383. {
  11384.     int ret = enemy::defend(wpnId, power, edef);
  11385.    
  11386.     if(ret < 0 && (flycnt||flycnt2))
  11387.         return 0;
  11388.        
  11389.     return ret;
  11390. }
  11391.  
  11392. esPatraBS::esPatraBS(fix X,fix Y,int Id,int Clk) : enemy(X,Y,Id,Clk)
  11393. {
  11394.     //cs=csBOSS;
  11395.     item_set=0;
  11396.     misc=clk;
  11397.     clk = -((misc*21)>>1)-1;
  11398.     yofs=playing_field_offset;
  11399.     hyofs=2;
  11400.     hxsz=hysz=16;
  11401.     bgsfx=-1;
  11402.     mainguy=count_enemy=false;
  11403.     deadsfx = WAV_EDEAD;
  11404.     hitsfx = WAV_EHIT;
  11405.     flags &= ~guy_neverret;
  11406. }
  11407.  
  11408. bool esPatraBS::animate(int index)
  11409. {
  11410.     if(dying)
  11411.         return Dead(index);
  11412.    
  11413.     return enemy::animate(index);
  11414. }
  11415.  
  11416. void esPatraBS::draw(BITMAP *dest)
  11417. {
  11418.     tile=o_tile;
  11419.    
  11420.     if(get_bit(quest_rules,qr_NEWENEMYTILES))
  11421.     {
  11422.         switch(dir)                                             //directions get screwed up after 8.  *shrug*
  11423.         {
  11424.         case up:                                              //u
  11425.             flip=0;
  11426.             break;
  11427.            
  11428.         case down:                                            //d
  11429.             flip=0;
  11430.             tile+=4;
  11431.             break;
  11432.            
  11433.         case left:                                            //l
  11434.             flip=0;
  11435.             tile+=8;
  11436.             break;
  11437.            
  11438.         case right:                                           //r
  11439.             flip=0;
  11440.             tile+=12;
  11441.             break;
  11442.            
  11443.         case l_up:                                            //ul
  11444.             flip=0;
  11445.             tile+=20;
  11446.             break;
  11447.            
  11448.         case r_up:                                            //ur
  11449.             flip=0;
  11450.             tile+=24;
  11451.             break;
  11452.            
  11453.         case l_down:                                          //dl
  11454.             flip=0;
  11455.             tile+=28;
  11456.             break;
  11457.            
  11458.         case r_down:                                          //dr
  11459.             flip=0;
  11460.             tile+=32;
  11461.             break;
  11462.         }
  11463.        
  11464.         tile += ((clk&6)>>1);
  11465.     }
  11466.     else
  11467.     {
  11468.         tile += (clk&4)?1:0;
  11469.     }
  11470.    
  11471.     if(clk>=0)
  11472.         enemy::draw(dest);
  11473. }
  11474.  
  11475.  
  11476. /**********************************/
  11477. /**********  Misc Code  ***********/
  11478. /**********************************/
  11479.  
  11480. void addEwpn(int x,int y,int z,int id,int type,int power,int dir, int parentid)
  11481. {
  11482.     if(id>wEnemyWeapons || (id >= wScript1 && id <= wScript10))
  11483.         Ewpns.add(new weapon((fix)x,(fix)y,(fix)z,id,type,power,dir, -1, parentid));
  11484. }
  11485.  
  11486. int hit_enemy(int index, int wpnId,int power,int wpnx,int wpny,int dir, int enemyHitWeapon)
  11487. {
  11488.     // Kludge
  11489.     weapon *w = new weapon((fix)wpnx,(fix)wpny,(fix)0,wpnId,0,power,dir,enemyHitWeapon,-1,false);
  11490.     int ret= ((enemy*)guys.spr(index))->takehit(w);
  11491.     delete w;
  11492.     return ret;
  11493. }
  11494.  
  11495. void enemy_scored(int index)
  11496. {
  11497.     ((enemy*)guys.spr(index))->scored=true;
  11498. }
  11499.  
  11500. void addguy(int x,int y,int id,int clk,bool mainguy)
  11501. {
  11502.     guy *g = new guy((fix)x,(fix)(y+(isdungeon()?1:0)),id,get_bit(quest_rules,qr_NOGUYPOOF)?0:clk,mainguy);
  11503.     guys.add(g);
  11504. }
  11505.  
  11506. void additem(int x,int y,int id,int pickup)
  11507. {
  11508.     item *i = new item(fix(x), fix(y - get_bit(quest_rules, qr_NOITEMOFFSET)), fix(0), id, pickup, 0);
  11509.     items.add(i);
  11510. }
  11511.  
  11512. void additem(int x,int y,int id,int pickup,int clk)
  11513. {
  11514.     item *i = new item((fix)x,(fix)y-(get_bit(quest_rules, qr_NOITEMOFFSET)),(fix)0,id,pickup,clk);
  11515.     items.add(i);
  11516. }
  11517.  
  11518. void kill_em_all()
  11519. {
  11520.     for(int i=0; i<guys.Count(); i++)
  11521.     {
  11522.         enemy *e = ((enemy*)guys.spr(i));
  11523.        
  11524.         if(e->flags&(1<<3) && !(e->family == eeGHINI && e->dmisc1 == 1)) continue;
  11525.        
  11526.         e->kickbucket();
  11527.     }
  11528. }
  11529.  
  11530. // For Link's hit detection. Don't count them if they are stunned or are guys.
  11531. int GuyHit(int tx,int ty,int tz,int txsz,int tysz,int tzsz)
  11532. {
  11533.     for(int i=0; i<guys.Count(); i++)
  11534.     {
  11535.         if(guys.spr(i)->hit(tx,ty,tz,txsz,tysz,tzsz))
  11536.         {
  11537.             if(((enemy*)guys.spr(i))->stunclk==0 && (!get_bit(quest_rules, qr_SAFEENEMYFADE) || ((enemy*)guys.spr(i))->fading != fade_flicker)
  11538.                     &&(((enemy*)guys.spr(i))->d->family != eeGUY || ((enemy*)guys.spr(i))->dmisc1))
  11539.             {
  11540.                 return i;
  11541.             }
  11542.         }
  11543.     }
  11544.    
  11545.     return -1;
  11546. }
  11547.  
  11548. // For Link's hit detection. Count them if they are dying.
  11549. int GuyHit(int index,int tx,int ty,int tz,int txsz,int tysz,int tzsz)
  11550. {
  11551.     enemy *e = (enemy*)guys.spr(index);
  11552.    
  11553.     if(e->hp > 0)
  11554.         return -1;
  11555.        
  11556.     bool d = e->dying;
  11557.     int hc = e->hclk;
  11558.     e->dying = false;
  11559.     e->hclk = 0;
  11560.     bool hit = e->hit(tx,ty,tz,txsz,tysz,tzsz);
  11561.     e->dying = d;
  11562.     e->hclk = hc;
  11563.    
  11564.     return hit ? index : -1;
  11565. }
  11566.  
  11567. bool hasMainGuy()
  11568. {
  11569.     for(int i=0; i<guys.Count(); i++)
  11570.     {
  11571.         if(((enemy*)guys.spr(i))->mainguy)
  11572.         {
  11573.             return true;
  11574.         }
  11575.     }
  11576.    
  11577.     return false;
  11578. }
  11579.  
  11580. void EatLink(int index)
  11581. {
  11582.     ((eStalfos*)guys.spr(index))->eatlink();
  11583. }
  11584.  
  11585. void GrabLink(int index)
  11586. {
  11587.     ((eWallM*)guys.spr(index))->grablink();
  11588. }
  11589.  
  11590. bool CarryLink()
  11591. {
  11592.     for(int i=0; i<guys.Count(); i++)
  11593.     {
  11594.         if(((guy*)(guys.spr(i)))->family==eeWALLM)
  11595.         {
  11596.             if(((eWallM*)guys.spr(i))->haslink)
  11597.             {
  11598.                 Link.x=guys.spr(i)->x;
  11599.                 Link.y=guys.spr(i)->y;
  11600.                 return ((eWallM*)guys.spr(i))->misc > 0;
  11601.             }
  11602.         }
  11603.        
  11604.         // Like Likes currently can't carry Link.
  11605.         /*
  11606.         if(((guy*)(guys.spr(i)))->family==eeLIKE)
  11607.         {
  11608.           if(((eLikeLike*)guys.spr(i))->haslink)
  11609.           {
  11610.             Link.x=guys.spr(i)->x;
  11611.             Link.y=guys.spr(i)->y;
  11612.             return (true);
  11613.           }
  11614.         }*/
  11615.     }
  11616.    
  11617.     return false;
  11618. }
  11619.  
  11620. // Move item with guy
  11621. void movefairy(fix &x,fix &y,int misc)
  11622. {
  11623.     int i = guys.idFirst(eITEMFAIRY+0x1000*misc);
  11624.    
  11625.     if(i!=-1)
  11626.     {
  11627.         x = guys.spr(i)->x;
  11628.         y = guys.spr(i)->y;
  11629.     }
  11630. }
  11631.  
  11632. // Move guy with item (used by FFC scripts and hookshot-dragged fairies)
  11633. void movefairy2(fix x,fix y,int misc)
  11634. {
  11635.     int i = guys.idFirst(eITEMFAIRY+0x1000*misc);
  11636.    
  11637.     if(i!=-1)
  11638.     {
  11639.         guys.spr(i)->x = x;
  11640.         guys.spr(i)->y = y;
  11641.     }
  11642. }
  11643.  
  11644. void killfairy(int misc)
  11645. {
  11646.     int i = guys.idFirst(eITEMFAIRY+0x1000*misc);
  11647.     guys.del(i);
  11648. }
  11649.  
  11650. int addenemy(int x,int y,int id,int clk)
  11651. {
  11652.     return addenemy(x,y,0,id,clk);
  11653. }
  11654.  
  11655. // Returns number of enemies/segments created
  11656. int addenemy(int x,int y,int z,int id,int clk)
  11657. {
  11658.     if(id <= 0) return 0;
  11659.    
  11660.     int ret = 0;
  11661.     sprite *e=NULL;
  11662.    
  11663.     switch(guysbuf[id&0xFFF].family)
  11664.     {
  11665.         //Fixme: possible enemy memory leak. (minor)
  11666.     case eeWALK:
  11667.         e = new eStalfos((fix)x,(fix)y,id,clk);
  11668.         break;
  11669.        
  11670.     case eeLEV:
  11671.         e = new eLeever((fix)x,(fix)y,id,clk);
  11672.         break;
  11673.        
  11674.     case eeTEK:
  11675.         e = new eTektite((fix)x,(fix)y,id,clk);
  11676.         break;
  11677.        
  11678.     case eePEAHAT:
  11679.         e = new ePeahat((fix)x,(fix)y,id,clk);
  11680.         break;
  11681.        
  11682.     case eeZORA:
  11683.         e = new eZora((fix)x,(fix)y,id,clk);
  11684.         break;
  11685.        
  11686.     case eeGHINI:
  11687.         e = new eGhini((fix)x,(fix)y,id,clk);
  11688.         break;
  11689.        
  11690.     case eeKEESE:
  11691.         e = new eKeese((fix)x,(fix)y,id,clk);
  11692.         break;
  11693.        
  11694.     case eeWIZZ:
  11695.         e = new eWizzrobe((fix)x,(fix)y,id,clk);
  11696.         break;
  11697.        
  11698.     case eePROJECTILE:
  11699.         e = new eProjectile((fix)x,(fix)y,id,clk);
  11700.         break;
  11701.        
  11702.     case eeWALLM:
  11703.         e = new eWallM((fix)x,(fix)y,id,clk);
  11704.         break;
  11705.        
  11706.     case eeAQUA:
  11707.         e = new eAquamentus((fix)x,(fix)y,id,clk);
  11708.         break;
  11709.        
  11710.     case eeMOLD:
  11711.         e = new eMoldorm((fix)x,(fix)y,id,zc_max(1,zc_min(254,guysbuf[id&0xFFF].misc1)));
  11712.         break;
  11713.        
  11714.     case eeMANHAN:
  11715.         e = new eManhandla((fix)x,(fix)y,id,clk);
  11716.         break;
  11717.        
  11718.     case eeGLEEOK:
  11719.         e = new eGleeok((fix)x,(fix)y,id,zc_max(1,zc_min(254,guysbuf[id&0xFFF].misc1)));
  11720.         break;
  11721.        
  11722.     case eeGHOMA:
  11723.         e = new eGohma((fix)x,(fix)y,id,clk);
  11724.         break;
  11725.        
  11726.     case eeLANM:
  11727.         e = new eLanmola((fix)x,(fix)y,id,zc_max(1,zc_min(253,guysbuf[id&0xFFF].misc1)));
  11728.         break;
  11729.        
  11730.     case eeGANON:
  11731.         e = new eGanon((fix)x,(fix)y,id,clk);
  11732.         break;
  11733.        
  11734.     case eeFAIRY:
  11735.         e = new eItemFairy((fix)x,(fix)y,id+0x1000*clk,clk);
  11736.         break;
  11737.        
  11738.     case eeFIRE:
  11739.         e = new eFire((fix)x,(fix)y,id,clk);
  11740.         break;
  11741.        
  11742.     case eeOTHER:
  11743.         e = new eOther((fix)x,(fix)y,id,clk);
  11744.         break;
  11745.        
  11746.     case eeSPINTILE:
  11747.         e = new eSpinTile((fix)x,(fix)y,id,clk);
  11748.         break;
  11749.        
  11750.         // and these enemies use the misc10/misc2 value
  11751.     case eeROCK:
  11752.     {
  11753.         switch(guysbuf[id&0xFFF].misc10)
  11754.         {
  11755.         case 1:
  11756.             e = new eBoulder((fix)x,(fix)y,id,clk);
  11757.             break;
  11758.            
  11759.         case 0:
  11760.         default:
  11761.             e = new eRock((fix)x,(fix)y,id,clk);
  11762.             break;
  11763.         }
  11764.        
  11765.         break;
  11766.     }
  11767.    
  11768.     case eeTRAP:
  11769.     {
  11770.         switch(guysbuf[id&0xFFF].misc2)
  11771.         {
  11772.         case 1:
  11773.             e = new eTrap2((fix)x,(fix)y,id,clk);
  11774.             break;
  11775.            
  11776.         case 0:
  11777.         default:
  11778.             e = new eTrap((fix)x,(fix)y,id,clk);
  11779.             break;
  11780.         }
  11781.        
  11782.         break;
  11783.     }
  11784.    
  11785.     case eeDONGO:
  11786.     {
  11787.         switch(guysbuf[id&0xFFF].misc10)
  11788.         {
  11789.         case 1:
  11790.             e = new eDodongo2((fix)x,(fix)y,id,clk);
  11791.             break;
  11792.            
  11793.         case 0:
  11794.         default:
  11795.             e = new eDodongo((fix)x,(fix)y,id,clk);
  11796.             break;
  11797.         }
  11798.        
  11799.         break;
  11800.     }
  11801.    
  11802.     case eeDIG:
  11803.     {
  11804.         switch(guysbuf[id&0xFFF].misc10)
  11805.         {
  11806.         case 1:
  11807.             e = new eLilDig((fix)x,(fix)y,id,clk);
  11808.             break;
  11809.            
  11810.         case 0:
  11811.         default:
  11812.             e = new eBigDig((fix)x,(fix)y,id,clk);
  11813.             break;
  11814.         }
  11815.        
  11816.         break;
  11817.     }
  11818.    
  11819.     case eePATRA:
  11820.     {
  11821.         switch(guysbuf[id&0xFFF].misc10)
  11822.         {
  11823.         case 1:
  11824.             e = new ePatraBS((fix)x,(fix)y,id,clk);
  11825.             break;
  11826.            
  11827.         case 0:
  11828.         default:
  11829.             e = new ePatra((fix)x,(fix)y,id,clk);
  11830.             break;
  11831.         }
  11832.        
  11833.         break;
  11834.     }
  11835.    
  11836.     case eeGUY:
  11837.     {
  11838.         switch(guysbuf[id&0xFFF].misc10)
  11839.         {
  11840.         case 1:
  11841.             e = new eTrigger((fix)x,(fix)y,id,clk);
  11842.             break;
  11843.            
  11844.         case 0:
  11845.         default:
  11846.             e = new eNPC((fix)x,(fix)y,id,clk);
  11847.             break;
  11848.         }
  11849.        
  11850.         break;
  11851.     }
  11852.    
  11853.     case eeNONE:
  11854.         if(guysbuf[id&0xFFF].misc10 ==1)
  11855.         {
  11856.             e = new eTrigger((fix)x,(fix)y,id,clk);
  11857.             break;
  11858.             break;
  11859.         }
  11860.        
  11861.     default:
  11862.    
  11863.         return 0;
  11864.     }
  11865.    
  11866.     ret++; // Made one enemy.
  11867.    
  11868.     if(z && canfall(id))
  11869.     {
  11870.         e->z = (fix)z;
  11871.     }
  11872.    
  11873.     ((enemy*)e)->ceiling = (z && canfall(id));
  11874.    
  11875.     if(!guys.add(e))
  11876.     {
  11877.         return 0;
  11878.     }
  11879.    
  11880.     // add segments of segmented enemies
  11881.     int c=0;
  11882.    
  11883.     switch(guysbuf[id&0xFFF].family)
  11884.     {
  11885.     case eeMOLD:
  11886.     {
  11887.         byte is=((enemy*)guys.spr(guys.Count()-1))->item_set;
  11888.         id &= 0xFFF;
  11889.        
  11890.         for(int i=0; i<zc_max(1,zc_min(254,guysbuf[id].misc1)); i++)
  11891.         {
  11892.             //christ this is messy -DD
  11893.             int segclk = -i*((int)(8.0/(fix(guysbuf[id&0xFFF].step/100.0))));
  11894.            
  11895.             if(!guys.add(new esMoldorm((fix)x,(fix)y,id+0x1000,segclk)))
  11896.             {
  11897.                 al_trace("Moldorm segment %d could not be created!\n",i+1);
  11898.                
  11899.                 for(int j=0; j<i+1; j++)
  11900.                     guys.del(guys.Count()-1);
  11901.                    
  11902.                 return 0;
  11903.             }
  11904.            
  11905.             if(i>0)
  11906.                 ((enemy*)guys.spr(guys.Count()-1))->item_set=is;
  11907.                
  11908.             ret++;
  11909.         }
  11910.        
  11911.         break;
  11912.     }
  11913.    
  11914.     case eeLANM:
  11915.     {
  11916.         id &= 0xFFF;
  11917.         int shft = guysbuf[id].misc2;
  11918.         byte is=((enemy*)guys.spr(guys.Count()-1))->item_set;
  11919.        
  11920.         if(!guys.add(new esLanmola((fix)x,(fix)y,id+0x1000,0)))
  11921.         {
  11922.             al_trace("Lanmola segment 1 could not be created!\n");
  11923.             guys.del(guys.Count()-1);
  11924.             return 0;
  11925.         }
  11926.        
  11927.         ret++;
  11928.        
  11929.         for(int i=1; i<zc_max(1,zc_min(253,guysbuf[id&0xFFF].misc1)); i++)
  11930.         {
  11931.             if(!guys.add(new esLanmola((fix)x,(fix)y,id+0x2000,-(i<<shft))))
  11932.             {
  11933.                 al_trace("Lanmola segment %d could not be created!\n",i+1);
  11934.                
  11935.                 for(int j=0; j<i+1; j++)
  11936.                     guys.del(guys.Count()-1);
  11937.                    
  11938.                 return 0;
  11939.             }
  11940.            
  11941.             ((enemy*)guys.spr(guys.Count()-1))->item_set=is;
  11942.             ret++;
  11943.         }
  11944.     }
  11945.     break;
  11946.    
  11947.     case eeMANHAN:
  11948.         id &= 0xFFF;
  11949.        
  11950.         for(int i=0; i<((!(guysbuf[id].misc2))?4:8); i++)
  11951.         {
  11952.             if(!guys.add(new esManhandla((fix)x,(fix)y,id+0x1000,i)))
  11953.             {
  11954.                 al_trace("Manhandla head %d could not be created!\n",i+1);
  11955.                
  11956.                 for(int j=0; j<i+1; j++)
  11957.                 {
  11958.                     guys.del(guys.Count()-1);
  11959.                 }
  11960.                
  11961.                 return 0;
  11962.             }
  11963.            
  11964.             ret++;
  11965.             ((enemy*)guys.spr(guys.Count()-1))->frate=guysbuf[id].misc1;
  11966.         }
  11967.        
  11968.         break;
  11969.        
  11970.     case eeGLEEOK:
  11971.     {
  11972.         id &= 0xFFF;
  11973.        
  11974.         for(int i=0; i<zc_max(1,zc_min(254,guysbuf[id&0xFFF].misc1)); i++)
  11975.         {
  11976.             if(!guys.add(new esGleeok((fix)x,(fix)y,id+0x1000,c, e)))
  11977.             {
  11978.                 al_trace("Gleeok head %d could not be created!\n",i+1);
  11979.                
  11980.                 for(int j=0; j<i+1; j++)
  11981.                 {
  11982.                     guys.del(guys.Count()-1);
  11983.                 }
  11984.                
  11985.                 return false;
  11986.             }
  11987.            
  11988.             c-=guysbuf[id].misc4;
  11989.             ret++;
  11990.         }
  11991.     }
  11992.     break;
  11993.    
  11994.    
  11995.     case eePATRA:
  11996.     {
  11997.         id &= 0xFFF;
  11998.         int outeyes = 0;
  11999.        
  12000.         for(int i=0; i<zc_min(254,guysbuf[id&0xFFF].misc1); i++)
  12001.         {
  12002.             if(!(guysbuf[id].misc10?guys.add(new esPatraBS((fix)x,(fix)y,id+0x1000,i)):guys.add(new esPatra((fix)x,(fix)y,id+0x1000,i))))
  12003.             {
  12004.                 al_trace("Patra outer eye %d could not be created!\n",i+1);
  12005.                
  12006.                 for(int j=0; j<i+1; j++)
  12007.                     guys.del(guys.Count()-1);
  12008.                    
  12009.                 return 0;
  12010.             }
  12011.             else
  12012.                 outeyes++;
  12013.                
  12014.             ret++;
  12015.         }
  12016.        
  12017.         for(int i=0; i<zc_min(254,guysbuf[id&0xFFF].misc2); i++)
  12018.         {
  12019.             if(!guys.add(new esPatra((fix)x,(fix)y,id+0x1000,i)))
  12020.             {
  12021.                 al_trace("Patra inner eye %d could not be created!\n",i+1);
  12022.                
  12023.                 for(int j=0; j<i+1+zc_min(254,outeyes); j++)
  12024.                     guys.del(guys.Count()-1);
  12025.                    
  12026.                 return 0;
  12027.             }
  12028.            
  12029.             ret++;
  12030.         }
  12031.        
  12032.         break;
  12033.     }
  12034.     }
  12035.    
  12036.     return ret;
  12037. }
  12038.  
  12039. bool isjumper(int id)
  12040. {
  12041.     switch(guysbuf[id&0xFFF].family)
  12042.     {
  12043.     case eeROCK:
  12044.     case eeTEK:
  12045.         return true;
  12046.        
  12047.     case eeWALK:
  12048.         if(guysbuf[id&0xFFF].misc9==e9tVIRE || guysbuf[id&0xFFF].misc9==e9tPOLSVOICE) return true;
  12049.     }
  12050.    
  12051.     return false;
  12052. }
  12053.  
  12054.  
  12055. bool isfixedtogrid(int id)
  12056. {
  12057.     switch(guysbuf[id&0xFFF].family)
  12058.     {
  12059.     case eeWALK:
  12060.     case eeLEV:
  12061.     case eeZORA:
  12062.     case eeDONGO:
  12063.     case eeGANON:
  12064.     case eeROCK:
  12065.     case eeGLEEOK:
  12066.     case eeAQUA:
  12067.     case eeLANM:
  12068.         return true;
  12069.     }
  12070.    
  12071.     return false;
  12072. }
  12073.  
  12074. // Can't fall, can have Z value.
  12075. bool isflier(int id)
  12076. {
  12077.     switch(guysbuf[id&0xFFF].family) //id&0x0FFF)
  12078.     {
  12079.     case eePEAHAT:
  12080.     case eeKEESE:
  12081.     case eePATRA:
  12082.     case eeFAIRY:
  12083.     case eeGHINI:
  12084.    
  12085.         // Could theoretically have their Z set by a script
  12086.     case eeFIRE:
  12087.         return true;
  12088.         break;
  12089.     }
  12090.    
  12091.     return false;
  12092. }
  12093.  
  12094. // Can't have Z position
  12095. bool never_in_air(int id)
  12096. {
  12097.     switch(guysbuf[id&0xFFF].family)
  12098.     {
  12099.     case eeMANHAN:
  12100.     case eeMOLD:
  12101.     case eeLANM:
  12102.     case eeGLEEOK:
  12103.     case eeZORA:
  12104.     case eeLEV:
  12105.     case eeAQUA:
  12106.     case eeROCK:
  12107.     case eeGANON:
  12108.     case eeTRAP:
  12109.     case eePROJECTILE:
  12110.     case eeSPINTILE:
  12111.         return true;
  12112.     }
  12113.    
  12114.     return false;
  12115. }
  12116.  
  12117. bool canfall(int id)
  12118. {
  12119.     switch(guysbuf[id&0xFFF].family)
  12120.     {
  12121.     case eeGUY:
  12122.     {
  12123.         if(id < eOCTO1S)
  12124.             return false;
  12125.            
  12126.         switch(guysbuf[id&0xFFF].misc10)
  12127.         {
  12128.         case 1:
  12129.         case 2:
  12130.             return true;
  12131.            
  12132.         case 0:
  12133.         case 3:
  12134.         default:
  12135.             return false;
  12136.         }
  12137.        
  12138.         case eeGHOMA:
  12139.         case eeDIG:
  12140.             return false;
  12141.         }
  12142.     }
  12143.    
  12144.     return !never_in_air(id) && !isflier(id) && !isjumper(id);
  12145. }
  12146.  
  12147. void addfires()
  12148. {
  12149.     if(!get_bit(quest_rules,qr_NOGUYFIRES))
  12150.     {
  12151.         int bs = get_bit(quest_rules,qr_BSZELDA);
  12152.         addguy(bs? 64: 72,64,gFIRE,-17,false);
  12153.         addguy(bs?176:168,64,gFIRE,-18,false);
  12154.     }
  12155. }
  12156.  
  12157. void loadguys()
  12158. {
  12159.     if(loaded_guys)
  12160.         return;
  12161.        
  12162.     loaded_guys=true;
  12163.    
  12164.     byte Guy=0;
  12165.     // When in caves/item rooms, use mBELOW and ipONETIME2
  12166.     // Else use mITEM and ipONETIME
  12167.     int mf = (currscr>=128) ? mBELOW : mITEM;
  12168.     int onetime = (currscr>=128) ? ipONETIME2 : ipONETIME;
  12169.    
  12170.     repaircharge=0;
  12171.     adjustmagic=false;
  12172.     learnslash=false;
  12173.    
  12174.     for(int i=0; i<3; i++)
  12175.     {
  12176.         prices[i]=0;
  12177.     }
  12178.    
  12179.     hasitem=0;
  12180.    
  12181.     if(currscr>=128 && DMaps[currdmap].flags&dmfGUYCAVES)
  12182.     {
  12183.         if(DMaps[currdmap].flags&dmfCAVES)
  12184.         {
  12185.             Guy=tmpscr[1].guy;
  12186.         }
  12187.     }
  12188.     else
  12189.     {
  12190.         Guy=tmpscr->guy;
  12191.        
  12192.         if(DMaps[currdmap].flags&dmfVIEWMAP)
  12193.             game->maps[(currmap*MAPSCRSNORMAL)+currscr] |= mVISITED;          // mark as visited
  12194.     }
  12195.    
  12196.     // The Guy appears if 'Link is in cave' equals 'Guy is in cave'.
  12197.     if(Guy && ((currscr>=128) == !!(DMaps[currdmap].flags&dmfGUYCAVES)))
  12198.     {
  12199.         if(tmpscr->room==rZELDA)
  12200.         {
  12201.             addguy(120,72,Guy,-15,true);
  12202.             guys.spr(0)->hxofs=1000;
  12203.             addenemy(128,96,eFIRE,-15);
  12204.             addenemy(112,96,eFIRE,-15);
  12205.             addenemy(96,120,eFIRE,-15);
  12206.             addenemy(144,120,eFIRE,-15);
  12207.             return;
  12208.         }
  12209.        
  12210.         if(Guy!=gFAIRY || !get_bit(quest_rules,qr_NOFAIRYGUYFIRES))
  12211.             addfires();
  12212.            
  12213.         if(currscr>=128)
  12214.             if(getmapflag())
  12215.                 Guy=0;
  12216.                
  12217.         switch(tmpscr->room)
  12218.         {
  12219.         case rSP_ITEM:
  12220.         case rMONEY:
  12221.         case rGRUMBLE:
  12222.         case rBOMBS:
  12223.         case rARROWS:
  12224.         case rSWINDLE:
  12225.         case rMUPGRADE:
  12226.         case rLEARNSLASH:
  12227.         case rTAKEONE:
  12228.         case rREPAIR:
  12229.         case rRP_HC:
  12230.             if(getmapflag())
  12231.                 Guy=0;
  12232.                
  12233.             break;
  12234.            
  12235.         case rTRIFORCE:
  12236.         {
  12237.             int tc = TriforceCount();
  12238.            
  12239.             if(get_bit(quest_rules,qr_4TRI))
  12240.             {
  12241.                 if((get_bit(quest_rules,qr_3TRI) && tc>=3) || tc>=4)
  12242.                     Guy=0;
  12243.             }
  12244.             else
  12245.             {
  12246.                 if((get_bit(quest_rules,qr_3TRI) && tc>=6) || tc>=8)
  12247.                     Guy=0;
  12248.             }
  12249.         }
  12250.         break;
  12251.         }
  12252.        
  12253.         if(Guy)
  12254.         {
  12255.             if(Guy!=gFAIRY || !get_bit(quest_rules,qr_NOFAIRYGUYFIRES))
  12256.                 blockpath=true;
  12257.                
  12258.             if(currscr<128)
  12259.                 Backend::sfx->play(WAV_SCALE,128);
  12260.                
  12261.             addguy(120,64,Guy, (dlevel||BSZ)?-15:startguy[rand()&7], true);
  12262.             Link.Freeze();
  12263.         }
  12264.     }
  12265.     else if(Guy==gFAIRY)  // The only Guy that somewhat ignores the "Guys In Caves Only" DMap flag
  12266.     {
  12267.         Backend::sfx->play(WAV_SCALE,128);
  12268.         addguy(120,62,gFAIRY,-14,false);
  12269.     }
  12270.    
  12271.     loaditem();
  12272.    
  12273.     // Collecting a rupee in a '10 Rupees' screen sets the mITEM screen state if
  12274.     // it doesn't appear in a Cave/Item Cellar, and the mBELOW screen state if it does.
  12275.     if(tmpscr->room==r10RUPIES && !getmapflag(mf))
  12276.     {
  12277.         //setmapflag();
  12278.         for(int i=0; i<10; i++)
  12279.             additem(ten_rupies_x[i],ten_rupies_y[i],0,ipBIGRANGE+onetime,-14);
  12280.     }
  12281. }
  12282.  
  12283. void loaditem()
  12284. {
  12285.     byte Item = 0;
  12286.    
  12287.     if(currscr<128)
  12288.     {
  12289.         Item=tmpscr->item;
  12290.        
  12291.         if(!getmapflag(mITEM) && (tmpscr->hasitem != 0))
  12292.         {
  12293.             if(tmpscr->flags&fITEM)
  12294.                 hasitem=1;
  12295.             else if(tmpscr->enemyflags&efCARRYITEM)
  12296.                 hasitem=4; // Will be set to 2 by roaming_item
  12297.             else
  12298.                 items.add(new item((fix)tmpscr->itemx,
  12299.                                    (tmpscr->flags7&fITEMFALLS && tmpscr->flags7&fSIDEVIEW) ? (fix)-170 : (fix)tmpscr->itemy+(get_bit(quest_rules, qr_NOITEMOFFSET)?0:1),
  12300.                                    (tmpscr->flags7&fITEMFALLS && !(tmpscr->flags7&fSIDEVIEW)) ? (fix)170 : (fix)0,
  12301.                                    Item,ipONETIME+ipBIGRANGE+((itemsbuf[Item].family==itype_triforcepiece ||
  12302.                                            (tmpscr->flags3&fHOLDITEM)) ? ipHOLDUP : 0),0));
  12303.         }
  12304.     }
  12305.     else if(!(DMaps[currdmap].flags&dmfCAVES))
  12306.     {
  12307.         if(!getmapflag() && tmpscr[1].room==rSP_ITEM
  12308.                 && (currscr==128 || !get_bit(quest_rules,qr_ITEMSINPASSAGEWAYS)))
  12309.         {
  12310.             Item=tmpscr[1].catchall;
  12311.            
  12312.             if(Item)
  12313.                 items.add(new item((fix)tmpscr->itemx,
  12314.                                    (tmpscr->flags7&fITEMFALLS && tmpscr->flags7&fSIDEVIEW) ? (fix)-170 : (fix)tmpscr->itemy+(get_bit(quest_rules, qr_NOITEMOFFSET)?0:1),
  12315.                                    (tmpscr->flags7&fITEMFALLS && !(tmpscr->flags7&fSIDEVIEW)) ? (fix)170 : (fix)0,
  12316.                                    Item,ipONETIME2|ipBIGRANGE|ipHOLDUP,0));
  12317.         }
  12318.     }
  12319. }
  12320.  
  12321. void never_return(int index)
  12322. {
  12323.     if(!get_bit(quest_rules,qr_KILLALL))
  12324.         goto doit;
  12325.        
  12326.     for(int i=0; i<guys.Count(); i++)
  12327.         if(((((enemy*)guys.spr(i))->d->flags)&guy_neverret) && i!=index)
  12328.         {
  12329.             goto dontdoit;
  12330.         }
  12331.        
  12332. doit:
  12333.     setmapflag(mNEVERRET);
  12334. dontdoit:
  12335.     return;
  12336. }
  12337.  
  12338. bool slowguy(int id)
  12339. {
  12340. //return (guysbuf[id].step<100);
  12341.     switch(id)
  12342.     {
  12343.     case eOCTO1S:
  12344.     case eOCTO2S:
  12345.     case eOCTO1F:
  12346.     case eOCTO2F:
  12347.     case eLEV1:
  12348.     case eLEV2:
  12349.     case eROCK:
  12350.     case eBOULDER:
  12351.         return true;
  12352.     }
  12353.    
  12354.     return false;
  12355. }
  12356.  
  12357. bool countguy(int id)
  12358. {
  12359.     id=id; //This is here to prevent a compiler warning.
  12360.     //The only argument this ever receives is tmpscr->enemy[i], which means
  12361.     // an entry in the screen's enemy list. Thus, it should always be counted. Right? - L.
  12362.     return true;
  12363. }
  12364.  
  12365. bool ok2add(int id)
  12366. {
  12367.     if(getmapflag(mNEVERRET) && (guysbuf[id].flags & guy_neverret))
  12368.         return false;
  12369.        
  12370.     switch(guysbuf[id].family)
  12371.     {
  12372.         // I added a special case for shooters because having traps on the same screen
  12373.         // was preventing them from spawning due to TMPNORET. This means they will
  12374.         // never stay dead, though, so it may not be the best solution. - Saf
  12375.     case eePROJECTILE:
  12376.         return true;
  12377.        
  12378.     case eeGANON:
  12379.     case eeTRAP:
  12380.         return false;
  12381.        
  12382.     case eeDIG:
  12383.     {
  12384.         switch(guysbuf[id].misc10)
  12385.         {
  12386.         case 1:
  12387.             if(!get_bit(quest_rules,qr_NOTMPNORET))
  12388.                 return !getmapflag(mTMPNORET);
  12389.                
  12390.             return true;
  12391.            
  12392.         case 0:
  12393.         default:
  12394.             return true;
  12395.         }
  12396.     }
  12397.     }
  12398.    
  12399.     if(!get_bit(quest_rules,qr_NOTMPNORET))
  12400.         return !getmapflag(mTMPNORET);
  12401.        
  12402.     return true;
  12403. }
  12404.  
  12405. void activate_fireball_statue(int pos)
  12406. {
  12407.     if(!(tmpscr->enemyflags&efFIREBALLS) || statueID<0)
  12408.     {
  12409.         return;
  12410.     }
  12411.    
  12412.     int cx=-1000, cy=-1000;
  12413.     int x = (pos&15)<<4;
  12414.     int y = pos&0xF0;
  12415.    
  12416.     int ctype = combobuf[MAPCOMBO(x,y)].type;
  12417.    
  12418.     if(!isfixedtogrid(statueID))
  12419.     {
  12420.         if(ctype==cL_STATUE)
  12421.         {
  12422.             cx=x+4;
  12423.             cy=y+7;
  12424.         }
  12425.         else if(ctype==cR_STATUE)
  12426.         {
  12427.             cx=x-8;
  12428.             cy=y-1;
  12429.         }
  12430.         else if(ctype==cC_STATUE)
  12431.         {
  12432.             cx=x;
  12433.             cy=y;
  12434.         }
  12435.     }
  12436.     else if(ctype==cL_STATUE || ctype==cR_STATUE || ctype==cC_STATUE)
  12437.     {
  12438.         cx=x;
  12439.         cy=y;
  12440.     }
  12441.    
  12442.     if(cx!=-1000)  // No point creating it if this is false
  12443.     {
  12444.         for(int j=0; j<guys.Count(); j++)
  12445.         {
  12446.             if((int(guys.spr(j)->x)==cx)&&(int(guys.spr(j)->y)==cy))
  12447.             {
  12448.                 if((guys.spr(j)->id&0xFFF) == statueID)  // There's already a matching enemy here!
  12449.                     return; // No point deleting it. A script might be toying with it in some way.
  12450.                 else
  12451.                     guys.del(j);
  12452.             }
  12453.         }
  12454.        
  12455.         addenemy(cx, cy, statueID, !isfixedtogrid(statueID) ? 24 : 0);
  12456.     }
  12457. }
  12458.  
  12459. void activate_fireball_statues()
  12460. {
  12461.     if(!(tmpscr->enemyflags&efFIREBALLS))
  12462.     {
  12463.         return;
  12464.     }
  12465.    
  12466.     for(int i=0; i<176; i++)
  12467.     {
  12468.         activate_fireball_statue(i);
  12469.     }
  12470. }
  12471.  
  12472. void load_default_enemies()
  12473. {
  12474.     wallm_load_clk=frame-80;
  12475.     int Id=0;
  12476.    
  12477.     if(tmpscr->enemyflags&efZORA)
  12478.     {
  12479.         if(zoraID>=0)
  12480.             addenemy(-16, -16, zoraID, 0);
  12481.     }
  12482.    
  12483.     if(tmpscr->enemyflags&efTRAP4)
  12484.     {
  12485.         if(cornerTrapID>=0)
  12486.         {
  12487.             addenemy(32, 32, cornerTrapID, -14);
  12488.             addenemy(208, 32, cornerTrapID, -14);
  12489.             addenemy(32, 128, cornerTrapID, -14);
  12490.             addenemy(208, 128, cornerTrapID, -14);
  12491.         }
  12492.     }
  12493.    
  12494.     for(int y=0; y<176; y+=16)
  12495.     {
  12496.         for(int x=0; x<256; x+=16)
  12497.         {
  12498.             int ctype = combobuf[MAPCOMBO(x,y)].type;
  12499.             int cflag = MAPFLAG(x, y);
  12500.             int cflag2 = MAPCOMBOFLAG(x, y);
  12501.            
  12502.             if(ctype==cTRAP_H || cflag==mfTRAP_H || cflag2==mfTRAP_H)
  12503.             {
  12504.                 if(trapLOSHorizontalID>=0)
  12505.                     addenemy(x, y, trapLOSHorizontalID, -14);
  12506.             }
  12507.             else if(ctype==cTRAP_V || cflag==mfTRAP_V || cflag2==mfTRAP_V)
  12508.             {
  12509.                 if(trapLOSVerticalID>=0)
  12510.                     addenemy(x, y, trapLOSVerticalID, -14);
  12511.             }
  12512.             else if(ctype==cTRAP_4 || cflag==mfTRAP_4 || cflag2==mfTRAP_4)
  12513.             {
  12514.                 if(trapLOS4WayID>=0)
  12515.                 {
  12516.                     if(addenemy(x, y, trapLOS4WayID, -14))
  12517.                         guys.spr(guys.Count()-1)->dummy_int[1]=2;
  12518.                 }
  12519.             }
  12520.            
  12521.             else if(ctype==cTRAP_LR || cflag==mfTRAP_LR || cflag2==mfTRAP_LR)
  12522.             {
  12523.                 if(trapConstantHorizontalID>=0)
  12524.                     addenemy(x, y, trapConstantHorizontalID, -14);
  12525.             }
  12526.             else if(ctype==cTRAP_UD || cflag==mfTRAP_UD || cflag2==mfTRAP_UD)
  12527.             {
  12528.                 if(trapConstantVerticalID>=0)
  12529.                     addenemy(x, y, trapConstantVerticalID, -14);
  12530.             }
  12531.            
  12532.             if(ctype==cSPINTILE1)
  12533.             {
  12534.                 // Awaken spinning tile
  12535.                 awaken_spinning_tile(tmpscr,COMBOPOS(x,y));
  12536.             }
  12537.         }
  12538.     }
  12539.    
  12540.     if(tmpscr->enemyflags&efTRAP2)
  12541.     {
  12542.         if(centerTrapID>=-1)
  12543.         {
  12544.             if(addenemy(64, 80, centerTrapID, -14))
  12545.                 guys.spr(guys.Count()-1)->dummy_int[1]=1;
  12546.            
  12547.             if(addenemy(176, 80, centerTrapID, -14))
  12548.                 guys.spr(guys.Count()-1)->dummy_int[1]=1;
  12549.         }
  12550.     }
  12551.    
  12552.     if(tmpscr->enemyflags&efROCKS)
  12553.     {
  12554.         if(rockID>=0)
  12555.         {
  12556.             addenemy(rand()&0xF0, 0, rockID, 0);
  12557.             addenemy(rand()&0xF0, 0, rockID, 0);
  12558.             addenemy(rand()&0xF0, 0, rockID, 0);
  12559.         }
  12560.     }
  12561.    
  12562.     activate_fireball_statues();
  12563. }
  12564.  
  12565.  
  12566. // Everything that must be done before we change a screen's combo to another combo, or a combo's type to another type.
  12567. // There's 2 routines because it's unclear if combobuf or tmpscr->data gets modified. -L
  12568. void screen_combo_modify_preroutine(mapscr *s, int pos)
  12569. {
  12570.     delete_fireball_shooter(s, pos);
  12571. }
  12572.  
  12573. // Everything that must be done after we change a screen's combo to another combo. -L
  12574. void screen_combo_modify_postroutine(mapscr *s, int pos)
  12575. {
  12576.     activate_fireball_statue(pos);
  12577.    
  12578.     if(combobuf[s->data[pos]].type==cSPINTILE1)
  12579.     {
  12580.         // Awaken spinning tile
  12581.         awaken_spinning_tile(s,pos);
  12582.     }
  12583. }
  12584.  
  12585. void awaken_spinning_tile(mapscr *s, int pos)
  12586. {
  12587.     addenemy((pos&15)<<4,pos&0xF0,(s->cset[pos]<<12)+eSPINTILE1,animated_combo_table[s->data[pos]][1]+zc_max(1,combobuf[s->data[pos]].frames));
  12588. }
  12589.  
  12590.  
  12591. // It stands for next_side_pos
  12592. void nsp(bool random)
  12593. // moves sle_x and sle_y to the next position
  12594. {
  12595.     if(random)
  12596.     {
  12597.         if(rand()%2)
  12598.         {
  12599.             sle_x = (rand()%2) ? 0 : 240;
  12600.             sle_y = (rand()%10)*16;
  12601.         }
  12602.         else
  12603.         {
  12604.             sle_y = (rand()%2) ? 0 : 160;
  12605.             sle_x = (rand()%15)*16;
  12606.         }
  12607.        
  12608.         return;
  12609.     }
  12610.    
  12611.     if(sle_x==0)
  12612.     {
  12613.         if(sle_y<160)
  12614.             sle_y+=16;
  12615.         else
  12616.             sle_x+=16;
  12617.     }
  12618.     else if(sle_y==160)
  12619.     {
  12620.         if(sle_x<240)
  12621.             sle_x+=16;
  12622.         else
  12623.             sle_y-=16;
  12624.     }
  12625.     else if(sle_x==240)
  12626.     {
  12627.         if(sle_y>0)
  12628.             sle_y-=16;
  12629.         else
  12630.             sle_x-=16;
  12631.     }
  12632.     else if(sle_y==0)
  12633.     {
  12634.         if(sle_x>0)
  12635.             sle_x-=16;
  12636.         else
  12637.             sle_y+=16;
  12638.     }
  12639. }
  12640.  
  12641. int next_side_pos(bool random)
  12642. // moves sle_x and sle_y to the next available position
  12643. // returns the direction the enemy should face
  12644. {
  12645.     bool blocked;
  12646.     int c=0;
  12647.    
  12648.     do
  12649.     {
  12650.         nsp(c>35 ? false : random);
  12651.         blocked = _walkflag(sle_x,sle_y,2) || _walkflag(sle_x,sle_y+8,2) ||
  12652.                   (combo_class_buf[COMBOTYPE(sle_x,sle_y)].block_enemies ||
  12653.                    MAPFLAG(sle_x,sle_y) == mfNOENEMY || MAPCOMBOFLAG(sle_x,sle_y)==mfNOENEMY ||
  12654.                    MAPFLAG(sle_x,sle_y) == mfNOGROUNDENEMY || MAPCOMBOFLAG(sle_x,sle_y)==mfNOGROUNDENEMY ||
  12655.                    iswater(MAPCOMBO(sle_x,sle_y)));
  12656.                    
  12657.         if(++c>50)
  12658.             return -1;
  12659.     }
  12660.     while(blocked);
  12661.    
  12662.     int dir=0;
  12663.    
  12664.     if(sle_x==0)    dir=right;
  12665.    
  12666.     if(sle_y==0)    dir=down;
  12667.    
  12668.     if(sle_x==240)  dir=left;
  12669.    
  12670.     if(sle_y==168)  dir=up;
  12671.    
  12672.     return dir;
  12673. }
  12674.  
  12675. bool can_side_load(int id)
  12676. {
  12677.     switch(guysbuf[id].family) //id&0x0FFF)
  12678.     {
  12679.         //case eTEK1:
  12680.         //case eTEK2:
  12681.         //case eTEK3:
  12682.         //case eLEV1:
  12683.         //case eLEV2:
  12684.         //case eLEV3:
  12685.         //case eRAQUAM:
  12686.         //case eLAQUAM:
  12687.         //case eDODONGO:
  12688.         //case eMANHAN:
  12689.         //case eGLEEOK1:
  12690.         //case eGLEEOK2:
  12691.         //case eGLEEOK3:
  12692.         //case eGLEEOK4:
  12693.         //case eDIG1:
  12694.         //case eDIG3:
  12695.         //case eGOHMA1:
  12696.         //case eGOHMA2:
  12697.         //case eCENT1:
  12698.         //case eCENT2:
  12699.         //case ePATRA1:
  12700.         //case ePATRA2:
  12701.         //case eGANON:
  12702.         //case eMANHAN2:
  12703.         //case eCEILINGM: later
  12704.         //case eFLOORM: later
  12705.         //case ePATRABS:
  12706.         //case ePATRAL2:
  12707.         //case ePATRAL3:
  12708.         //case eGLEEOK1F:
  12709.         //case eGLEEOK2F:
  12710.         //case eGLEEOK3F:
  12711.         //case eGLEEOK4F:
  12712.         //case eDODONGOBS:
  12713.         //case eDODONGOF:
  12714.         //case eGOHMA3:
  12715.         //case eGOHMA4:
  12716.         //case eSHOOTMAGIC:
  12717.         //case eSHOOTROCK:
  12718.         //case eSHOOTSPEAR:
  12719.         //case eSHOOTSWORD:
  12720.         //case eSHOOTFLAME:
  12721.         //case eSHOOTFLAME2:
  12722.         //case eSHOOTFBALL:
  12723.     case eeTEK:
  12724.     case eeLEV:
  12725.     case eeAQUA:
  12726.     case eeDONGO:
  12727.     case eeMANHAN:
  12728.     case eeGLEEOK:
  12729.     case eeDIG:
  12730.     case eeGHOMA:
  12731.     case eeLANM:
  12732.     case eePATRA:
  12733.     case eeGANON:
  12734.     case eePROJECTILE:
  12735.         return false;
  12736.         break;
  12737.     }
  12738.    
  12739.     return true;
  12740. }
  12741.  
  12742.  
  12743. void side_load_enemies()
  12744. {
  12745.     if(sle_clk==0)
  12746.     {
  12747.         sle_cnt = 0;
  12748.         int guycnt = 0;
  12749.         short s = (currmap<<7)+currscr;
  12750.         bool beenhere=false;
  12751.         bool reload=true;
  12752.         bool reloadspecial = false;
  12753.        
  12754.         load_default_enemies();
  12755.        
  12756.         for(int i=0; i<6; i++)
  12757.             if(visited[i]==s)
  12758.                 beenhere=true;
  12759.                
  12760.         if(!beenhere)
  12761.         {
  12762.             visited[vhead]=s;
  12763.             vhead = (vhead+1)%6;
  12764.         }
  12765.         else if(game->guys[s]==0)
  12766.         {
  12767.             sle_cnt=0;
  12768.             reload=false;
  12769.             reloadspecial = true;
  12770.         }
  12771.        
  12772.         if(reload)
  12773.         {
  12774.             sle_cnt = game->guys[s];
  12775.            
  12776.             if(sle_cnt==0)
  12777.             {
  12778.                 while(sle_cnt<10 && tmpscr->enemy[sle_cnt]!=0)
  12779.                     ++sle_cnt;
  12780.             }
  12781.             else
  12782.                 reloadspecial = true;
  12783.         }
  12784.        
  12785.         if((get_bit(quest_rules,qr_ALWAYSRET)) || (tmpscr->flags3&fENEMIESRETURN))
  12786.         {
  12787.             sle_cnt = 0;
  12788.             reloadspecial = false;
  12789.            
  12790.             while(sle_cnt<10 && tmpscr->enemy[sle_cnt]!=0)
  12791.                 ++sle_cnt;
  12792.         }
  12793.        
  12794.         if(reloadspecial)
  12795.         {
  12796.             for(int i=0; !countguy(tmpscr->enemy[i]) && sle_cnt<10; i++)
  12797.                 ++sle_cnt;
  12798.         }
  12799.        
  12800.         for(int i=0; i<sle_cnt; i++)
  12801.             if(countguy(tmpscr->enemy[i]))
  12802.                 ++guycnt;
  12803.                
  12804.         game->guys[s] = guycnt;
  12805.     }
  12806.    
  12807.     if((++sle_clk+8)%24 == 0)
  12808.     {
  12809.         int dir = next_side_pos(tmpscr->pattern==pSIDESR);
  12810.        
  12811.         if(dir==-1 || tooclose(sle_x,sle_y,32))
  12812.         {
  12813.             return;
  12814.         }
  12815.        
  12816.         int enemy_slot=guys.Count();
  12817.        
  12818.         while(sle_cnt > 0 && !ok2add(tmpscr->enemy[sle_cnt-1]))
  12819.             sle_cnt--;
  12820.            
  12821.         if(sle_cnt > 0)
  12822.         {
  12823.             if(addenemy(sle_x,sle_y,tmpscr->enemy[--sle_cnt],0))
  12824.                 guys.spr(enemy_slot)->dir = dir;
  12825.         }
  12826.     }
  12827.    
  12828.     if(sle_cnt<=0)
  12829.         loaded_enemies=true;
  12830. }
  12831.  
  12832. bool is_starting_pos(int i, int x, int y, int t)
  12833. {
  12834.     // No corner enemies
  12835.     if((x==0 || x==240) && (y==0 || y==160))
  12836.         return false;
  12837.        
  12838.     // No enemies in dungeon walls
  12839.     if(isdungeon() && (x<32 || x>=224 || y<32 || y>=144))
  12840.         return false;
  12841.        
  12842.     // Too close
  12843.     if(tooclose(x,y,40) && t<11)
  12844.         return false;
  12845.        
  12846.     // Can't fly onto it?
  12847.     if(isflier(tmpscr->enemy[i])&&
  12848.             (flyerblocked(x+8,y+8,spw_floater)||
  12849.              (_walkflag(x,y+8,2)&&!get_bit(quest_rules,qr_WALLFLIERS))))
  12850.         return false;
  12851.        
  12852.     // Can't jump onto it?
  12853.     if(guysbuf[tmpscr->enemy[i]].family==eeTEK &&
  12854.             (COMBOTYPE(x+8,y+8)==cNOJUMPZONE||
  12855.              COMBOTYPE(x+8,y+8)==cNOENEMY||
  12856.              MAPFLAG(x+8,y+8)==mfNOENEMY||
  12857.              MAPCOMBOFLAG(x+8,y+8)==mfNOENEMY))
  12858.         return false;
  12859.        
  12860.     // Other off-limit combos
  12861.     if((!isflier(tmpscr->enemy[i])&& guysbuf[tmpscr->enemy[i]].family!=eeTEK &&
  12862.             (_walkflag(x,y+8,2) || groundblocked(x+8,y+8))) &&
  12863.             guysbuf[tmpscr->enemy[i]].family!=eeZORA)
  12864.         return false;
  12865.        
  12866.     // Don't ever generate enemies on these combos!
  12867.     if(COMBOTYPE(x+8,y+8)==cARMOS||COMBOTYPE(x+8,y+8)==cBSGRAVE)
  12868.         return false;
  12869.        
  12870.     //BS Dodongos need at least 2 spaces.
  12871.     if((guysbuf[tmpscr->enemy[i]].family==eeDONGO)&&(guysbuf[tmpscr->enemy[i]].misc10==1))
  12872.     {
  12873.         if(((x<16) ||_walkflag(x-16,y+8, 2))&&
  12874.                 ((x>224)||_walkflag(x+16,y+8, 2))&&
  12875.                 ((y<16) ||_walkflag(x,   y-8, 2))&&
  12876.                 ((y>144)||_walkflag(x,   y+24,2)))
  12877.         {
  12878.             return false;
  12879.         }
  12880.     }
  12881.    
  12882.     return true;
  12883. }
  12884.  
  12885. bool is_ceiling_pattern(int i)
  12886. {
  12887.     return (i==pCEILING || i==pCEILINGR);
  12888. }
  12889.  
  12890. int placeenemy(int i)
  12891. {
  12892.     std::map<int, int> freeposcache;
  12893.     int frees = 0;
  12894.    
  12895.     for(int y=0; y<176; y+=16)
  12896.     {
  12897.         for(int x=0; x<256; x+=16)
  12898.         {
  12899.             if(is_starting_pos(i,x,y,0))
  12900.             {
  12901.                 freeposcache[frees++] = (y&0xF0)+(x>>4);
  12902.             }
  12903.         }
  12904.     }
  12905.    
  12906.     if(frees > 0)
  12907.         return freeposcache[rand()%frees];
  12908.        
  12909.     return -1;
  12910. }
  12911.  
  12912. void loadenemies()
  12913. {
  12914.     if(loaded_enemies)
  12915.         return;
  12916.        
  12917.     // check if it's the dungeon boss and it has been beaten before
  12918.     if(tmpscr->enemyflags&efBOSS && game->lvlitems[dlevel]&liBOSS)
  12919.     {
  12920.         loaded_enemies = true;
  12921.         return;
  12922.     }
  12923.    
  12924.     if(tmpscr->pattern==pSIDES || tmpscr->pattern==pSIDESR)
  12925.     {
  12926.         side_load_enemies();
  12927.         return;
  12928.     }
  12929.    
  12930.     loaded_enemies=true;
  12931.    
  12932.     // do enemies that are always loaded
  12933.     load_default_enemies();
  12934.    
  12935.     // dungeon basements
  12936.    
  12937.     static byte dngn_enemy_x[4] = {32,96,144,208};
  12938.    
  12939.     if(currscr>=128)
  12940.     {
  12941.         if(DMaps[currdmap].flags&dmfCAVES) return;
  12942.        
  12943.         for(int i=0; i<4; i++)
  12944.             addenemy(dngn_enemy_x[i],96,tmpscr->enemy[i]?tmpscr->enemy[i]:(int)eKEESE1,-14-i);
  12945.            
  12946.         return;
  12947.     }
  12948.    
  12949.     // check if it's been long enough to reload all enemies
  12950.    
  12951.     int loadcnt = 10;
  12952.     short s = (currmap<<7)+currscr;
  12953.     bool beenhere = false;
  12954.     bool reload = true;
  12955.    
  12956.     for(int i=0; i<6; i++)
  12957.         if(visited[i]==s)
  12958.             beenhere = true;
  12959.            
  12960.     if(!beenhere)
  12961.     {
  12962.         visited[vhead]=s;
  12963.         vhead = (vhead+1)%6;
  12964.     }
  12965.     else if(game->guys[s]==0)
  12966.     {
  12967.         loadcnt = 0;
  12968.         reload  = false;
  12969.     }
  12970.    
  12971.     if(reload)
  12972.     {
  12973.         loadcnt = game->guys[s];
  12974.        
  12975.         if(loadcnt==0)
  12976.             loadcnt = 10;
  12977.     }
  12978.    
  12979.     if((get_bit(quest_rules,qr_ALWAYSRET)) || (tmpscr->flags3&fENEMIESRETURN))
  12980.         loadcnt = 10;
  12981.        
  12982.     for(int i=0; !countguy(tmpscr->enemy[i]) && loadcnt<10; i++)
  12983.         ++loadcnt;
  12984.        
  12985.     // load enemies
  12986.    
  12987.     //if(true)                    // enemies appear at random places
  12988.     //{
  12989.     //int set=loadside*9;
  12990.     int pos=rand()%9;
  12991.     int clk=-15,x=0,y=0,fastguys=0;
  12992.     int i=0,guycnt=0;
  12993.    
  12994.     for(; i<loadcnt && tmpscr->enemy[i]>0; i++)             /* i=0 */
  12995.     {
  12996.         bool placed=false;
  12997.         int t=-1;
  12998.        
  12999.         // First: enemy combo flags
  13000.         for(int sy=0; sy<176; sy+=16)
  13001.         {
  13002.             for(int sx=0; sx<256; sx+=16)
  13003.             {
  13004.                 int cflag = MAPFLAG(sx, sy);
  13005.                 int cflag2 = MAPCOMBOFLAG(sx, sy);
  13006.                
  13007.                 if(((cflag==mfENEMY0+i)||(cflag2==mfENEMY0+i)) && (!placed))
  13008.                 {
  13009.                     if(!ok2add(tmpscr->enemy[i]))
  13010.                         ++loadcnt;
  13011.                     else
  13012.                     {
  13013.                         addenemy(sx,
  13014.                                  (is_ceiling_pattern(tmpscr->pattern) && tmpscr->flags7&fSIDEVIEW) ? -(150+50*guycnt) : sy,
  13015.                                  (is_ceiling_pattern(tmpscr->pattern) && !(tmpscr->flags7&fSIDEVIEW)) ? 150+50*guycnt : 0,tmpscr->enemy[i],-15);
  13016.                                  
  13017.                         if(countguy(tmpscr->enemy[i]))
  13018.                             ++guycnt;
  13019.                            
  13020.                         placed=true;
  13021.                         goto placed_enemy;
  13022.                     }
  13023.                 }
  13024.             }
  13025.         }
  13026.        
  13027.         // Next: enemy pattern
  13028.         if((tmpscr->pattern==pRANDOM || tmpscr->pattern==pCEILING) && !(tmpscr->flags7&fSIDEVIEW))
  13029.         {
  13030.             do
  13031.             {
  13032.                 // NES positions
  13033.                 pos%=9;
  13034.                 x=stx[loadside][pos];
  13035.                 y=sty[loadside][pos];
  13036.                 ++pos;
  13037.                 ++t;
  13038.             }
  13039.             while((t< 20) && !is_starting_pos(i,x,y,t));
  13040.         }
  13041.        
  13042.         if(t<0 || t >= 20) // above enemy pattern failed
  13043.         {
  13044.             // Final chance: find a random position anywhere onscreen
  13045.             int randpos = placeenemy(i);
  13046.            
  13047.             if(randpos>-1)
  13048.             {
  13049.                 x=(randpos&15)<<4;
  13050.                 y= randpos&0xF0;
  13051.             }
  13052.             else // All opportunities failed - abort
  13053.             {
  13054.                 --clk;
  13055.                 continue;
  13056.             }
  13057.         }
  13058.        
  13059.         {
  13060.             int c=0;
  13061.             c=clk;
  13062.            
  13063.             if(!slowguy(tmpscr->enemy[i]))
  13064.                 ++fastguys;
  13065.             else if(fastguys>0)
  13066.                 c=-15*(i-fastguys+2);
  13067.             else
  13068.                 c=-15*(i+1);
  13069.                
  13070.             if(BSZ)
  13071.             {
  13072.                 // Special case for blue leevers
  13073.                 if(guysbuf[tmpscr->enemy[i]].family==eeLEV && guysbuf[tmpscr->enemy[i]].misc1==1)
  13074.                     c=-15*(i+1);
  13075.                 else
  13076.                     c=-15;
  13077.             }
  13078.            
  13079.             if(!ok2add(tmpscr->enemy[i]))
  13080.                 ++loadcnt;
  13081.             else
  13082.             {
  13083.                 addenemy(x,(is_ceiling_pattern(tmpscr->pattern) && tmpscr->flags7&fSIDEVIEW) ? -(150+50*guycnt) : y,
  13084.                          (is_ceiling_pattern(tmpscr->pattern) && !(tmpscr->flags7&fSIDEVIEW)) ? 150+50*guycnt : 0,tmpscr->enemy[i],c);
  13085.                          
  13086.                 if(countguy(tmpscr->enemy[i]))
  13087.                     ++guycnt;
  13088.             }
  13089.            
  13090.             placed=true;
  13091.         }                                                     // if(t < 20)
  13092.        
  13093. placed_enemy:
  13094.        
  13095.         // I don't like this, but it seems to work...
  13096.         static bool foundCarrier;
  13097.        
  13098.         if(i==0)
  13099.             foundCarrier=false;
  13100.        
  13101.         if(placed)
  13102.         {
  13103.             if(i==0 && tmpscr->enemyflags&efLEADER)
  13104.             {
  13105.                 int index = guys.idFirst(tmpscr->enemy[i],0xFFF);
  13106.                
  13107.                 if(index!=-1)
  13108.                 {
  13109.                     ((enemy*)guys.spr(index))->leader = true;
  13110.                 }
  13111.             }
  13112.            
  13113.             if(!foundCarrier && (hasitem)>1)
  13114.             {
  13115.                 int index = guys.idFirst(tmpscr->enemy[i],0xFFF);
  13116.                
  13117.                 if(index!=-1 && (((enemy*)guys.spr(index))->flags&guy_doesntcount)==0)
  13118.                 {
  13119.                     ((enemy*)guys.spr(index))->itemguy = true;
  13120.                     foundCarrier=true;
  13121.                 }
  13122.             }
  13123.         }
  13124.        
  13125.         --clk;
  13126.     }                                                       // for
  13127.    
  13128.     game->guys[s] = guycnt;
  13129.     //} //if(true)
  13130. }
  13131.  
  13132. void moneysign()
  13133. {
  13134.     additem(48,108,iRupy,ipDUMMY);
  13135.     //  textout(scrollbuf,zfont,"X",64,112,CSET(0)+1);
  13136.     set_clip_state(pricesdisplaybuf, 0);
  13137.     textout_ex(pricesdisplaybuf,zfont,"X",64,112,CSET(0)+1,-1);
  13138. }
  13139.  
  13140. void putprices(bool sign)
  13141. {
  13142.     // refresh what's under the prices
  13143.     // for(int i=5; i<12; i++)
  13144.     //   putcombo(scrollbuf,i<<4,112,tmpscr->data[112+i],tmpscr->cpage);
  13145.    
  13146.     rectfill(pricesdisplaybuf, 72, 112, pricesdisplaybuf->w-1, pricesdisplaybuf->h-1, 0);
  13147.     int step=32;
  13148.     int x=80;
  13149.    
  13150.     if(prices[2]==0)
  13151.     {
  13152.         step<<=1;
  13153.        
  13154.         if(prices[1]==0)
  13155.         {
  13156.             x=112;
  13157.         }
  13158.     }
  13159.    
  13160.     for(int i=0; i<3; i++)
  13161.     {
  13162.         // Kind of stupid, but it works: 100000 is used to indicate that an item
  13163.         // has a price of zero rather than there being no item.
  13164.         // 100000 isn't a valid price, so this doesn't cause problems.
  13165.         if(prices[i]!=0 && prices[i]<100000)
  13166.         {
  13167.             char buf[8];
  13168.             sprintf(buf,sign?"%+3d":"%3d",prices[i]);
  13169.            
  13170.             int l=(int)strlen(buf);
  13171.             set_clip_state(pricesdisplaybuf, 0);
  13172.             textout_ex(pricesdisplaybuf,zfont,buf,x-(l>3?(l-3)<<3:0),112,CSET(0)+1,-1);
  13173.         }
  13174.        
  13175.         x+=step;
  13176.     }
  13177. }
  13178.  
  13179. // Setting up special rooms
  13180. // Also called when the Letter is used successfully.
  13181. void setupscreen()
  13182. {
  13183.     boughtsomething=false;
  13184.     int t=currscr<128?0:1;
  13185.     word str=tmpscr[t].str;
  13186.    
  13187.     // Prices are already set to 0 in dowarp()
  13188.     switch(tmpscr[t].room)
  13189.     {
  13190.     case rSP_ITEM:                                          // special item
  13191.         additem(120,89,tmpscr[t].catchall,ipONETIME2+ipHOLDUP+ipCHECK);
  13192.         break;
  13193.        
  13194.     case rINFO:                                             // pay for info
  13195.     {
  13196.         int count = 0;
  13197.         int base  = 88;
  13198.         int step  = 5;
  13199.        
  13200.         moneysign();
  13201.        
  13202.         for(int i=0; i<3; i++)
  13203.         {
  13204.             if(QMisc.info[tmpscr[t].catchall].str[i])
  13205.             {
  13206.                 ++count;
  13207.             }
  13208.             else
  13209.                 break;
  13210.         }
  13211.        
  13212.         if(count)
  13213.         {
  13214.             if(count==1)
  13215.             {
  13216.                 base = 88+32;
  13217.             }
  13218.            
  13219.             if(count==2)
  13220.             {
  13221.                 step = 6;
  13222.             }
  13223.            
  13224.             for(int i=0; i < count; i++)
  13225.             {
  13226.                 additem((i << step)+base, 89, iRupy, ipMONEY + ipDUMMY);
  13227.                 ((item*)items.spr(items.Count()-1))->PriceIndex = i;
  13228.                 prices[i] = -(QMisc.info[tmpscr[t].catchall].price[i]);
  13229.                 if(prices[i]==0)
  13230.                     prices[i]=100000; // So putprices() knows there's an item here and positions the price correctly
  13231.                 int itemid = current_item_id(itype_wealthmedal);
  13232.                
  13233.                 if(itemid>=0 && prices[i]!=100000)
  13234.                 {
  13235.                     if(itemsbuf[itemid].flags & ITEM_FLAG1)
  13236.                         prices[i]=((prices[i]*itemsbuf[itemid].misc1)/100);
  13237.                     else
  13238.                         prices[i]-=itemsbuf[itemid].misc1;
  13239.                     prices[i]=vbound(prices[i], -99999, 0);
  13240.                     if(prices[i]==0)
  13241.                         prices[i]=100000;
  13242.                 }
  13243.                
  13244.                 if((QMisc.info[tmpscr[t].catchall].price[i])>1 && prices[i]>-1 && prices[i]!=100000)
  13245.                     prices[i]=-1;
  13246.             }
  13247.         }
  13248.        
  13249.         break;
  13250.     }
  13251.    
  13252.     case rMONEY:                                            // secret money
  13253.         additem(120,89,iRupy,ipONETIME+ipDUMMY+ipMONEY);
  13254.         ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
  13255.         break;
  13256.        
  13257.     case rGAMBLE:                                           // gambling
  13258.         prices[0]=prices[1]=prices[2]=-10;
  13259.         moneysign();
  13260.         additem(88,89,iRupy,ipMONEY+ipDUMMY);
  13261.         ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
  13262.         additem(120,89,iRupy,ipMONEY+ipDUMMY);
  13263.         ((item*)items.spr(items.Count()-1))->PriceIndex = 1;
  13264.         additem(152,89,iRupy,ipMONEY+ipDUMMY);
  13265.         ((item*)items.spr(items.Count()-1))->PriceIndex = 2;
  13266.         break;
  13267.        
  13268.     case rREPAIR:                                           // door repair
  13269.         setmapflag();
  13270.         //  }
  13271.         repaircharge=tmpscr[t].catchall;
  13272.         break;
  13273.        
  13274.     case rMUPGRADE:                                         // upgrade magic
  13275.         adjustmagic=true;
  13276.         break;
  13277.        
  13278.     case rLEARNSLASH:                                       // learn slash attack
  13279.         learnslash=true;
  13280.         break;
  13281.        
  13282.     case rRP_HC:                                            // heart container or red potion
  13283.         additem(88,89,iRPotion,ipONETIME2+ipHOLDUP+ipFADE);
  13284.         ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
  13285.         additem(152,89,iHeartC,ipONETIME2+ipHOLDUP+ipFADE);
  13286.         ((item*)items.spr(items.Count()-1))->PriceIndex = 1;
  13287.         break;
  13288.        
  13289.     case rP_SHOP:                                           // potion shop
  13290.         if(current_item(itype_letter)<i_letter_used)
  13291.         {
  13292.             str=0;
  13293.             break;
  13294.         }
  13295.        
  13296.         // fall through
  13297.        
  13298.     case rTAKEONE:                                          // take one
  13299.     case rSHOP:                                             // shop
  13300.     {
  13301.         int count = 0;
  13302.         int base  = 88;
  13303.         int step  = 5;
  13304.        
  13305.         if(tmpscr[t].room != rTAKEONE)
  13306.             moneysign();
  13307.            
  13308.         //count and align the stuff
  13309.         for(int i=0; i<3; ++i)
  13310.         {
  13311.             if(QMisc.shop[tmpscr[t].catchall].hasitem[count] != 0)
  13312.             {
  13313.                 ++count;
  13314.             }
  13315.             else
  13316.             {
  13317.                 break;
  13318.             }
  13319.         }
  13320.        
  13321.         if(count==1)
  13322.         {
  13323.             base = 88+32;
  13324.         }
  13325.        
  13326.         if(count==2)
  13327.         {
  13328.             step = 6;
  13329.         }
  13330.        
  13331.         for(int i=0; i<count; i++)
  13332.         {
  13333.             additem((i<<step)+base, 89, QMisc.shop[tmpscr[t].catchall].item[i], ipHOLDUP+ipFADE+(tmpscr[t].room == rTAKEONE ? ipONETIME2 : ipCHECK));
  13334.             ((item*)items.spr(items.Count()-1))->PriceIndex = i;
  13335.            
  13336.             if(tmpscr[t].room != rTAKEONE)
  13337.             {
  13338.                 prices[i] = QMisc.shop[tmpscr[t].catchall].price[i];
  13339.                 if(prices[i]==0)
  13340.                     prices[i]=100000; // So putprices() knows there's an item here and positions the price correctly
  13341.                 int itemid = current_item_id(itype_wealthmedal);
  13342.                
  13343.                 if(itemid>=0 && prices[i]!=100000)
  13344.                 {
  13345.                     if(itemsbuf[itemid].flags & ITEM_FLAG1)
  13346.                         prices[i]=((prices[i]*itemsbuf[itemid].misc1)/100);
  13347.                     else
  13348.                         prices[i]+=itemsbuf[itemid].misc1;
  13349.                     prices[i]=vbound(prices[i], 0, 99999);
  13350.                     if(prices[i]==0)
  13351.                         prices[i]=100000;
  13352.                 }
  13353.                
  13354.                 if((QMisc.shop[tmpscr[t].catchall].price[i])>1 && prices[i]<1)
  13355.                     prices[i]=1;
  13356.             }
  13357.         }
  13358.        
  13359.         break;
  13360.     }
  13361.    
  13362.     case rBOMBS:                                            // more bombs
  13363.         additem(120,89,iRupy,ipDUMMY+ipMONEY);
  13364.         ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
  13365.         prices[0]=-tmpscr[t].catchall;
  13366.         break;
  13367.        
  13368.     case rARROWS:                                            // more arrows
  13369.         additem(120,89,iRupy,ipDUMMY+ipMONEY);
  13370.         ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
  13371.         prices[0]=-tmpscr[t].catchall;
  13372.         break;
  13373.        
  13374.     case rSWINDLE:                                          // leave heart container or money
  13375.         additem(88,89,iHeartC,ipDUMMY+ipMONEY);
  13376.         ((item*)items.spr(items.Count()-1))->PriceIndex = 0;
  13377.         prices[0]=-1;
  13378.         additem(152,89,iRupy,ipDUMMY+ipMONEY);
  13379.         ((item*)items.spr(items.Count()-1))->PriceIndex = 1;
  13380.         prices[1]=-tmpscr[t].catchall;
  13381.         break;
  13382.        
  13383.     }
  13384.    
  13385.     if(tmpscr[t].room == rBOMBS || tmpscr[t].room == rARROWS)
  13386.     {
  13387.         int i = (tmpscr[t].room == rSWINDLE ? 1 : 0);
  13388.         int itemid = current_item_id(itype_wealthmedal);
  13389.        
  13390.         if(itemid >= 0)
  13391.         {
  13392.             if(itemsbuf[itemid].flags & ITEM_FLAG1)
  13393.                 prices[i]*=(itemsbuf[itemid].misc1/100);
  13394.             else
  13395.                 prices[i]+=itemsbuf[itemid].misc1;
  13396.         }
  13397.        
  13398.         if(tmpscr[t].catchall>1 && prices[i]>-1)
  13399.             prices[i]=-1;
  13400.     }
  13401.    
  13402.     putprices(false);
  13403.    
  13404.     if(str)
  13405.     {
  13406.         donewmsg(str);
  13407.     }
  13408.     else
  13409.     {
  13410.         Link.unfreeze();
  13411.     }
  13412. }
  13413.  
  13414. // Increments msgptr and returns the control code argument pointed at.
  13415. word grab_next_argument()
  13416. {
  13417.     byte val=MsgStrings[msgstr].s[++msgptr]-1;
  13418.     word ret=val;
  13419.    
  13420.     // If an argument is succeeded by 255, then it's a three-byte argument -
  13421.     // between 254 and 65535 (or whatever the maximum actually is)
  13422.     if((unsigned char)(MsgStrings[msgstr].s[msgptr+1]) == 255)
  13423.     {
  13424.         val=MsgStrings[msgstr].s[msgptr+2];
  13425.         word next=val;
  13426.         ret += 254*next;
  13427.         msgptr+=2;
  13428.     }
  13429.    
  13430.     return ret;
  13431. }
  13432.  
  13433. bool parsemsgcode()
  13434. {
  13435.     if(msgptr>=MSGSIZE-2) return false;
  13436.    
  13437.     switch(MsgStrings[msgstr].s[msgptr]-1)
  13438.     {
  13439.     case MSGC_NEWLINE:
  13440.         cursor_y += text_height(msgfont) + MsgStrings[msgstr].vspace;
  13441.         cursor_x=0;
  13442.         return true;
  13443.        
  13444.     case MSGC_COLOUR:
  13445.     {
  13446.         int cset = (grab_next_argument());
  13447.         msgcolour = CSET(cset)+(grab_next_argument());
  13448.         return true;
  13449.     }
  13450.    
  13451.     case MSGC_SPEED:
  13452.         msgspeed=grab_next_argument();
  13453.         return true;
  13454.        
  13455.     case MSGC_CTRUP:
  13456.     {
  13457.         int a1 = grab_next_argument();
  13458.         int a2 = grab_next_argument();
  13459.         game->change_counter(a2, a1);
  13460.         return true;
  13461.     }
  13462.    
  13463.     case MSGC_CTRDN:
  13464.     {
  13465.         int a1 = grab_next_argument();
  13466.         int a2 = grab_next_argument();
  13467.         game->change_counter(-a2, a1);
  13468.         return true;
  13469.     }
  13470.    
  13471.     case MSGC_CTRSET:
  13472.     {
  13473.         int a1 = grab_next_argument();
  13474.         int a2 = grab_next_argument();
  13475.         game->set_counter(vbound(a2, 0, game->get_maxcounter(a1)), a1);
  13476.         return true;
  13477.     }
  13478.    
  13479.     case MSGC_CTRUPPC:
  13480.     case MSGC_CTRDNPC:
  13481.     case MSGC_CTRSETPC:
  13482.     {
  13483.         int code = MsgStrings[msgstr].s[msgptr]-1;
  13484.         int counter = grab_next_argument();
  13485.         int amount = grab_next_argument();
  13486.         amount = (int)(vbound(amount*0.01, 0, 1)*game->get_maxcounter(counter));
  13487.        
  13488.         if(code==MSGC_CTRDNPC)
  13489.             amount*=-1;
  13490.            
  13491.         if(code==MSGC_CTRSETPC)
  13492.             game->set_counter(amount, counter);
  13493.         else
  13494.             game->change_counter(amount, counter);
  13495.            
  13496.         return true;
  13497.     }
  13498.    
  13499.     case MSGC_GIVEITEM:
  13500.         getitem(grab_next_argument(), true);
  13501.         return true;
  13502.        
  13503.     case MSGC_TAKEITEM:
  13504.         takeitem(grab_next_argument());
  13505.         return true;
  13506.        
  13507.     case MSGC_SFX:
  13508.         Backend::sfx->play((int)grab_next_argument(),128);
  13509.         return true;
  13510.        
  13511.     case MSGC_MIDI:
  13512.     {
  13513.         int music = (int)(grab_next_argument());
  13514.        
  13515.         if(music==0)
  13516.             music_stop();
  13517.         else
  13518.             jukebox(music+(ZC_MIDI_COUNT-1));
  13519.            
  13520.         return true;
  13521.     }
  13522.    
  13523.     /*
  13524.         case MSGC_NAME:
  13525.           if (!((cBbtn()&&get_bit(quest_rules,qr_ALLOWMSGBYPASS)) || msgspeed==0))
  13526.             sfx(MsgStrings[msgstr].sfx);
  13527.           textprintf_ex(msgdisplaybuf,msgfont,((msgpos%24)<<3)+32,((msgpos/24)<<3)+zc_min(MsgStrings[msgstr].y,136)+8,msgcolour,-1,
  13528.                         "%s",game->get_name());
  13529.           return true;
  13530.     */
  13531.     case MSGC_GOTOIFRAND:
  13532.     {
  13533.         int odds = (int)(grab_next_argument());
  13534.        
  13535.         if(!((rand()%(2*odds))/odds))
  13536.             goto switched;
  13537.            
  13538.         (void)grab_next_argument();
  13539.         return true;
  13540.     }
  13541.    
  13542.     case MSGC_GOTOIFGLOBAL:
  13543.     {
  13544.         int arg = (int)grab_next_argument();
  13545.         int d = zc_min(7,arg);
  13546.         int s = ((get_currdmap())<<7) + get_currscr()-(DMaps[get_currdmap()].type==dmOVERW ? 0 : DMaps[get_currdmap()].xoff);
  13547.         arg = (int)grab_next_argument();
  13548.        
  13549.         if(game->screen_d[s][d] >= arg)
  13550.             goto switched;
  13551.            
  13552.         (void)grab_next_argument();
  13553.         return true;
  13554.     }
  13555.    
  13556.     case MSGC_GOTOIF:
  13557.     {
  13558.         int it = (int)grab_next_argument();
  13559.        
  13560.         if(it<MAXITEMS && game->item[it])
  13561.             goto switched;
  13562.            
  13563.         (void)grab_next_argument();
  13564.         return true;
  13565.     }
  13566.    
  13567.     case MSGC_GOTOIFCTR:
  13568.         if(game->get_counter(grab_next_argument())>=grab_next_argument())
  13569.             goto switched;
  13570.            
  13571.         (void)grab_next_argument();
  13572.         return true;
  13573.        
  13574.     case MSGC_GOTOIFCTRPC:
  13575.     {
  13576.         int counter = grab_next_argument();
  13577.         int amount = (int)(((grab_next_argument())/100)*game->get_maxcounter(counter));
  13578.        
  13579.         if(game->get_counter(counter)>=amount)
  13580.             goto switched;
  13581.            
  13582.         (void)grab_next_argument();
  13583.         return true;
  13584.     }
  13585.    
  13586.     case MSGC_GOTOIFTRICOUNT:
  13587.         if(TriforceCount() >= (int)(grab_next_argument()))
  13588.             goto switched;
  13589.            
  13590.         (void)grab_next_argument();
  13591.         return true;
  13592.        
  13593.     case MSGC_GOTOIFTRI:
  13594.     {
  13595.         int lev = (int)(grab_next_argument());
  13596.        
  13597.         if(lev<MAXLEVELS && game->lvlitems[lev]&liTRIFORCE)
  13598.             goto switched;
  13599.            
  13600.         (void)grab_next_argument();
  13601.         return true;
  13602.     }
  13603.    
  13604. #if 0
  13605.    
  13606.     case MSGC_GOTOIFYN:
  13607.     {
  13608.         bool done=false;
  13609.         int pos = 0;
  13610.         set_clip_state(msgdisplaybuf, 0);
  13611.        
  13612.         do // Copied from title.cpp...
  13613.         {
  13614.             int f=-1;
  13615.             bool done2=false;
  13616.             // TODO: Lower Y value limit
  13617.             textout_ex(msgdisplaybuf, msgfont,"YES",112,MsgStrings[msgstr].y+36,msgcolour,-1);
  13618.             textout_ex(msgdisplaybuf, msgfont,"NO",112,MsgStrings[msgstr].y+48,msgcolour,-1);
  13619.            
  13620.             do
  13621.             {
  13622.                 load_control_state();
  13623.                
  13624.                 if(f==-1)
  13625.                 {
  13626.                     if(rUp())
  13627.                     {
  13628.                         sfx(WAV_CHINK);
  13629.                         pos=0;
  13630.                     }
  13631.                    
  13632.                     if(rDown())
  13633.                     {
  13634.                         sfx(WAV_CHINK);
  13635.                         pos=1;
  13636.                     }
  13637.                    
  13638.                     if(rSbtn()) ++f;
  13639.                 }
  13640.                
  13641.                 if(f>=0)
  13642.                 {
  13643.                     if(++f == 65)
  13644.                         done2=true;
  13645.                        
  13646.                     if(!(f&3))
  13647.                     {
  13648.                         int c = (f&4) ? msgcolour : QMisc.colors.caption;
  13649.                        
  13650.                         switch(pos)
  13651.                         {
  13652.                         case 0:
  13653.                             textout_ex(msgdisplaybuf, msgfont,"YES",112,MsgStrings[msgstr].y+36,c,-1);
  13654.                             break;
  13655.                            
  13656.                         case 1:
  13657.                             textout_ex(msgdisplaybuf, msgfont,"NO",112,MsgStrings[msgstr].y+48,c,-1);
  13658.                             break;
  13659.                         }
  13660.                     }
  13661.                 }
  13662.                
  13663.                 rectfill(msgdisplaybuf,96,MsgStrings[msgstr].y+36,136,MsgStrings[msgstr].y+60,0);
  13664.                 overtile8(msgdisplaybuf,2,96,(pos*16)+MsgStrings[msgstr].y+36,1,0);
  13665.                 advanceframe(true);
  13666.             }
  13667.             while(!Quit && !done2);
  13668.            
  13669.             clear_bitmap(msgdisplaybuf);
  13670.             done=true;
  13671.         }
  13672.         while(!Quit && !done);
  13673.        
  13674.         if(pos==0)
  13675.             goto switched;
  13676.            
  13677.         ++msgptr;
  13678.         return true;
  13679.     }
  13680.    
  13681. #endif
  13682. switched:
  13683.     int lev = (int)(grab_next_argument());
  13684.     donewmsg(lev);
  13685.     msgptr--; // To counteract it being incremented after this routine is called.
  13686.     putprices(false);
  13687.     return true;
  13688.     }
  13689.    
  13690.     return false;
  13691. }
  13692.  
  13693. // Wraps the message string... probably.
  13694. void wrapmsgstr(char *s3)
  13695. {
  13696.     int j=0;
  13697.    
  13698.     if(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP)
  13699.     {
  13700.         if(msgspace)
  13701.         {
  13702.             if(MsgStrings[msgstr].s[msgptr] >= 32 && MsgStrings[msgstr].s[msgptr] <= 126)
  13703.             {
  13704.                 for(int k=0; MsgStrings[msgstr].s[msgptr+k] && MsgStrings[msgstr].s[msgptr+k] != ' '; k++)
  13705.                 {
  13706.                     if(MsgStrings[msgstr].s[msgptr+k] >= 32 && MsgStrings[msgstr].s[msgptr+k] <= 126) s3[j++] = MsgStrings[msgstr].s[msgptr+k];
  13707.                 }
  13708.                
  13709.                 s3[j] = 0;
  13710.                 msgspace = false;
  13711.             }
  13712.             else
  13713.             {
  13714.                 s3[0] = MsgStrings[msgstr].s[msgptr];
  13715.                 s3[1] = 0;
  13716.             }
  13717.         }
  13718.         else
  13719.         {
  13720.             s3[0] = MsgStrings[msgstr].s[msgptr];
  13721.             s3[1] = 0;
  13722.            
  13723.             if(s3[0] == ' ') msgspace=true;
  13724.         }
  13725.     }
  13726.     else
  13727.     {
  13728.         s3[0] = MsgStrings[msgstr].s[msgptr];
  13729.         s3[1] = 0;
  13730.     }
  13731. }
  13732.  
  13733. // Returns true if the pointer is at a string's
  13734. // null terminator or a trailing space
  13735. bool atend(char *str)
  13736. {
  13737.     int i=0;
  13738.    
  13739.     while(str[i]==' ')
  13740.         i++;
  13741.        
  13742.     return str[i]=='\0';
  13743. }
  13744.  
  13745. void putmsg()
  13746. {
  13747.     if(!msgorig) msgorig=msgstr;
  13748.    
  13749.     if(linkedmsgclk>0)
  13750.     {
  13751.         if(linkedmsgclk==1)
  13752.         {
  13753.             if(cAbtn()||cBbtn())
  13754.             {
  13755.                 msgstr=MsgStrings[msgstr].nextstring;
  13756.                
  13757.                 if(!msgstr)
  13758.                 {
  13759.                     msgfont=zfont;
  13760.                    
  13761.                     if(tmpscr->room!=rGRUMBLE)
  13762.                         blockpath=false;
  13763.                        
  13764.                     dismissmsg();
  13765.                     goto disappear;
  13766.                 }
  13767.                
  13768.                 donewmsg(msgstr);
  13769.                 putprices(false);
  13770.             }
  13771.         }
  13772.         else
  13773.         {
  13774.             --linkedmsgclk;
  13775.         }
  13776.     }
  13777.    
  13778.     if(!msgstr || msgpos>=10000 || msgptr>=MSGSIZE || cursor_y >= msg_h)
  13779.     {
  13780.         if(!msgstr)
  13781.             msgorig=0;
  13782.            
  13783.         msg_active = false;
  13784.         return;
  13785.     }
  13786.    
  13787.     msg_onscreen = true; // Now the message is onscreen (see donewmsg()).
  13788.    
  13789.     char s3[145];
  13790.     int tlength;
  13791.    
  13792.     // Bypass the string with the B button!
  13793.     if(((cBbtn())&&(get_bit(quest_rules,qr_ALLOWMSGBYPASS))) || msgspeed==0)
  13794.     {
  13795.         //finish writing out the string
  13796.         while(msgptr<MSGSIZE && !atend(MsgStrings[msgstr].s+msgptr))
  13797.         {
  13798.             if(msgspeed && !(cBbtn() && get_bit(quest_rules,qr_ALLOWMSGBYPASS)))
  13799.                 goto breakout; // break out if message speed was changed to non-zero
  13800.             else if(!parsemsgcode())
  13801.             {
  13802.                 if(cursor_y >= msg_h)
  13803.                     break;
  13804.                    
  13805.                 wrapmsgstr(s3);
  13806.                
  13807.                 if(MsgStrings[msgstr].s[msgptr]==' ')
  13808.                 {
  13809.                     tlength = msgfont->vtable->char_length(msgfont, MsgStrings[msgstr].s[msgptr]) + MsgStrings[msgstr].hspace;
  13810.                    
  13811.                     if(cursor_x+tlength > msg_w && ((cursor_x > msg_w || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP)) ? true : strcmp(s3," ")!=0))
  13812.                     {
  13813.                         cursor_y += text_height(msgfont) + MsgStrings[msgstr].vspace;
  13814.                         cursor_x=0;
  13815.                     }
  13816.                    
  13817.                     textprintf_ex(msgbmpbuf,msgfont,cursor_x+8,cursor_y+8,msgcolour,-1,
  13818.                                   "%c",MsgStrings[msgstr].s[msgptr]);
  13819.                     cursor_x+=tlength;
  13820.                 }
  13821.                 else
  13822.                 {
  13823.                     tlength = text_length(msgfont, s3) + ((int)strlen(s3)*MsgStrings[msgstr].hspace);
  13824.                    
  13825.                     if(cursor_x+tlength > msg_w && ((cursor_x > msg_w || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP)) ? true : strcmp(s3," ")!=0))
  13826.                     {
  13827.                         cursor_y += text_height(msgfont) + MsgStrings[msgstr].vspace;
  13828.                         cursor_x=0;
  13829.                     }
  13830.                    
  13831.                     Backend::sfx->play(MsgStrings[msgstr].sfx,128);
  13832.                     textprintf_ex(msgbmpbuf,msgfont,cursor_x+8,cursor_y+8,msgcolour,-1,
  13833.                                   "%c",MsgStrings[msgstr].s[msgptr]);
  13834.                     cursor_x += msgfont->vtable->char_length(msgfont, MsgStrings[msgstr].s[msgptr]);
  13835.                     cursor_x += MsgStrings[msgstr].hspace;
  13836.                 }
  13837.                
  13838.                 msgpos++;
  13839.             }
  13840.            
  13841.             ++msgptr;
  13842.            
  13843.             if(atend(MsgStrings[msgstr].s+msgptr))
  13844.             {
  13845.                 if(MsgStrings[msgstr].nextstring)
  13846.                 {
  13847.                     if(MsgStrings[MsgStrings[msgstr].nextstring].stringflags & STRINGFLAG_CONT)
  13848.                     {
  13849.                         msgstr=MsgStrings[msgstr].nextstring;
  13850.                         msgpos=msgptr=0;
  13851.                         msgfont=setmsgfont();
  13852.                     }
  13853.                 }
  13854.             }
  13855.         }
  13856.        
  13857.         msgclk=72;
  13858.         msgpos=10000;
  13859.     }
  13860.     else
  13861.     {
  13862. breakout:
  13863.  
  13864.         if(((msgclk++)%(msgspeed+1)<msgspeed)&&((!cAbtn())||(!get_bit(quest_rules,qr_ALLOWFASTMSG))))
  13865.             return;
  13866.     }
  13867.    
  13868.     // Start writing the string
  13869.     if(msgptr == 0)
  13870.     {
  13871.         while(MsgStrings[msgstr].s[msgptr]==' ')
  13872.         {
  13873.             tlength = msgfont->vtable->char_length(msgfont, MsgStrings[msgstr].s[msgptr]) + MsgStrings[msgstr].hspace;
  13874.            
  13875.             if(cursor_x+tlength > msg_w && ((cursor_x > msg_w || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP)) ? 1 : strcmp(s3," ")!=0))
  13876.             {
  13877.                 cursor_y += text_height(msgfont) + MsgStrings[msgstr].vspace;
  13878.                 cursor_x=0;
  13879.             }
  13880.            
  13881.             cursor_x+=tlength;
  13882.             ++msgptr;
  13883.             ++msgpos;
  13884.            
  13885.             // The "Continue From Previous" feature
  13886.             if(atend(MsgStrings[msgstr].s+msgptr))
  13887.             {
  13888.                 if(MsgStrings[msgstr].nextstring)
  13889.                 {
  13890.                     if(MsgStrings[MsgStrings[msgstr].nextstring].stringflags & STRINGFLAG_CONT)
  13891.                     {
  13892.                         msgstr=MsgStrings[msgstr].nextstring;
  13893.                         msgpos=msgptr=0;
  13894.                         msgfont=setmsgfont();
  13895.                     }
  13896.                 }
  13897.             }
  13898.         }
  13899.     }
  13900.    
  13901.     // Continue printing the string!
  13902.     if(!atend(MsgStrings[msgstr].s+msgptr) && cursor_y < msg_h)
  13903.     {
  13904.         if(!parsemsgcode())
  13905.         {
  13906.             wrapmsgstr(s3);
  13907.            
  13908.             tlength = text_length(msgfont, s3) + ((int)strlen(s3)*MsgStrings[msgstr].hspace);
  13909.            
  13910.             if(cursor_x+tlength > msg_w && ((cursor_x > msg_w || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP)) ? true : strcmp(s3," ")!=0))
  13911.             {
  13912.                 cursor_y += text_height(msgfont) + MsgStrings[msgstr].vspace;
  13913.                 cursor_x=0;
  13914.                 //if(space) s3[0]=0;
  13915.             }
  13916.            
  13917.             Backend::sfx->play(MsgStrings[msgstr].sfx,128);
  13918.             textprintf_ex(msgbmpbuf,msgfont,cursor_x+8,cursor_y+8,msgcolour,-1,
  13919.                           "%c",MsgStrings[msgstr].s[msgptr]);
  13920.             cursor_x += msgfont->vtable->char_length(msgfont, MsgStrings[msgstr].s[msgptr]);
  13921.             cursor_x += MsgStrings[msgstr].hspace;
  13922.             msgpos++;
  13923.         }
  13924.        
  13925.         msgptr++;
  13926.        
  13927.         if(atend(MsgStrings[msgstr].s+msgptr))
  13928.         {
  13929.             if(MsgStrings[msgstr].nextstring)
  13930.             {
  13931.                 if(MsgStrings[MsgStrings[msgstr].nextstring].stringflags & STRINGFLAG_CONT)
  13932.                 {
  13933.                     msgstr=MsgStrings[msgstr].nextstring;
  13934.                     msgpos=msgptr=0;
  13935.                     msgfont=setmsgfont();
  13936.                 }
  13937.             }
  13938.         }
  13939.        
  13940.         if((MsgStrings[msgstr].s[msgptr]==' ') && (MsgStrings[msgstr].s[msgptr+1]==' '))
  13941.             while(MsgStrings[msgstr].s[msgptr]==' ')
  13942.             {
  13943.                 tlength = msgfont->vtable->char_length(msgfont, MsgStrings[msgstr].s[msgptr]) + MsgStrings[msgstr].hspace;
  13944.                
  13945.                 if(cursor_x+tlength > msg_w && ((cursor_x > msg_w || !(MsgStrings[msgstr].stringflags & STRINGFLAG_WRAP)) ? true : strcmp(s3," ")!=0))
  13946.                 {
  13947.                     cursor_y += text_height(msgfont) + MsgStrings[msgstr].vspace;
  13948.                     cursor_x=0;
  13949.                 }
  13950.                
  13951.                 cursor_x+=tlength;
  13952.                 ++msgpos;
  13953.                 ++msgptr;
  13954.                
  13955.                 if(atend(MsgStrings[msgstr].s+msgptr))
  13956.                 {
  13957.                     if(MsgStrings[msgstr].nextstring)
  13958.                     {
  13959.                         if(MsgStrings[MsgStrings[msgstr].nextstring].stringflags & STRINGFLAG_CONT)
  13960.                         {
  13961.                             msgstr=MsgStrings[msgstr].nextstring;
  13962.                             msgpos=msgptr=0;
  13963.                             msgfont=setmsgfont();
  13964.                         }
  13965.                     }
  13966.                 }
  13967.             }
  13968.     }
  13969.    
  13970.     // Done printing the string
  13971.     if((msgpos>=10000 || msgptr>=MSGSIZE || cursor_y >= msg_h || atend(MsgStrings[msgstr].s+msgptr)) && !linkedmsgclk)
  13972.     {
  13973.         while(parsemsgcode()) // Finish remaining control codes
  13974.             ;
  13975.            
  13976.         // Go to next string, or make it disappear by going to string 0.
  13977.         if(MsgStrings[msgstr].nextstring!=0 || get_bit(quest_rules,qr_MSGDISAPPEAR))
  13978.         {
  13979.             linkedmsgclk=51;
  13980.         }
  13981.        
  13982.         if(MsgStrings[msgstr].nextstring==0)
  13983.         {
  13984.             if(!get_bit(quest_rules,qr_MSGDISAPPEAR))
  13985.             {
  13986. disappear:
  13987.                 msg_active = false;
  13988.                 Link.finishedmsg();
  13989.             }
  13990.            
  13991.             if(repaircharge)
  13992.             {
  13993.                 //       if (get_bit(quest_rules,qr_REPAIRFIX)) {
  13994.                 //         fixed_door=true;
  13995.                 //       }
  13996.                 game->change_drupy(-tmpscr[currscr<128?0:1].catchall);
  13997.                 repaircharge = 0;
  13998.             }
  13999.            
  14000.             if(adjustmagic)
  14001.             {
  14002.                 if(game->get_magicdrainrate())
  14003.                     game->set_magicdrainrate(1);
  14004.                    
  14005.                 adjustmagic = false;
  14006.                 Backend::sfx->play(WAV_SCALE,128);
  14007.                 setmapflag();
  14008.             }
  14009.            
  14010.             if(learnslash)
  14011.             {
  14012.                 game->set_canslash(1);
  14013.                 learnslash = false;
  14014.                 Backend::sfx->play(WAV_SCALE,128);
  14015.                 setmapflag();
  14016.             }
  14017.         }
  14018.     }
  14019. }
  14020.  
  14021. int message_more_y()
  14022. {
  14023.     //Is the flag ticked, do we really want a message more y larger than 160?
  14024.     int msgy=zc_min((zinit.msg_more_is_offset==0)?zinit.msg_more_y:zinit.msg_more_y+MsgStrings[msgstr].y ,160);
  14025.     msgy+=playing_field_offset;
  14026.     return msgy;
  14027. }
  14028.  
  14029. /***  Collision detection & handling  ***/
  14030.  
  14031. void check_collisions()
  14032. {
  14033.     for(int i=0; i<Lwpns.Count(); i++)
  14034.     {
  14035.         weapon *w = (weapon*)Lwpns.spr(i);
  14036.        
  14037.         if(!(w->Dead()) && w->id!=wSword && w->id!=wHammer && w->id!=wWand)
  14038.         {
  14039.             for(int j=0; j<guys.Count(); j++)
  14040.             {
  14041.                 enemy *e = (enemy*)guys.spr(j);
  14042.                
  14043.                 if(e->hit(w))
  14044.                 {
  14045.                     int h = e->takehit(w);
  14046.                    
  14047.                     // NOT FOR PUBLIC RELEASE
  14048.                     /*if(h==3) //Mirror shield
  14049.                     {
  14050.                     if (w->id==ewFireball || w->id==wRefFireball)
  14051.                     {
  14052.                       w->id=wRefFireball;
  14053.                       switch(e->dir)
  14054.                       {
  14055.                         case up:    e->angle += (PI - e->angle) * 2.0;      break;
  14056.                         case down:  e->angle = -e->angle;                   break;
  14057.                         case left:  e->angle += ((-PI/2) - e->angle) * 2.0; break;
  14058.                         case right: e->angle += (( PI/2) - e->angle) * 2.0; break;
  14059.                         // TODO: the following. -L.
  14060.                         case l_up:  break;
  14061.                         case r_up:  break;
  14062.                         case l_down: break;
  14063.                         case r_down: break;
  14064.                       }
  14065.                     }
  14066.                     else
  14067.                     {
  14068.                       w->id = ((w->id==ewMagic || w->id==wRefMagic || w->id==wMagic) ? wRefMagic : wRefBeam);
  14069.                       w->dir ^= 1;
  14070.                       if(w->dir&2)
  14071.                         w->flip ^= 1;
  14072.                       else
  14073.                         w->flip ^= 2;
  14074.                     }
  14075.                     w->ignoreLink=false;
  14076.                     }
  14077.                     else*/
  14078.                     if(h)
  14079.                     {
  14080.                         w->onhit(false);
  14081.                     }
  14082.                    
  14083.                     if(h==2)
  14084.                     {
  14085.                         break;
  14086.                     }
  14087.                 }
  14088.                
  14089.                 if(w->Dead())
  14090.                 {
  14091.                     break;
  14092.                 }
  14093.             }
  14094.            
  14095.             if(get_bit(quest_rules,qr_Z3BRANG_HSHOT))
  14096.             {
  14097.                 if(w->id == wBrang || w->id==wHookshot)
  14098.                 {
  14099.                     for(int j=0; j<items.Count(); j++)
  14100.                     {
  14101.                         if(items.spr(j)->hit(w))
  14102.                         {
  14103.                             bool priced = ((item*)items.spr(j))->PriceIndex >-1;
  14104.                            
  14105.                             if((((item*)items.spr(j))->pickup & ipTIMER && ((item*)items.spr(j))->clk2 >= 32)
  14106.                                     || (get_bit(quest_rules,qr_BRANGPICKUP) && !priced && !(((item*)items.spr(j))->pickup & ipDUMMY)))
  14107.                             {
  14108.                                 if(w->id == wBrang)
  14109.                                 {
  14110.                                     w->onhit(false);
  14111.                                 }
  14112.                                
  14113.                                 if(w->dragging==-1)
  14114.                                 {
  14115.                                     w->dead=1;
  14116.                                     /*if (w->id==wBrang&&w->dummy_bool[0]&&(w->misc==1))
  14117.                                     {
  14118.                                       add_grenade(w->x,w->y,w->z,(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_brang))>0,w->parentid);
  14119.                                       w->dummy_bool[0]=false;
  14120.                                     }*/
  14121.                                     ((item*)items.spr(j))->clk2=256;
  14122.                                     w->dragging=j;
  14123.                                 }
  14124.                             }
  14125.                         }
  14126.                     }
  14127.                 }
  14128.             }
  14129.             else
  14130.             {
  14131.                 if(w->id == wBrang || w->id == wArrow || w->id==wHookshot)
  14132.                 {
  14133.                     for(int j=0; j<items.Count(); j++)
  14134.                     {
  14135.                         if(items.spr(j)->hit(w))
  14136.                         {
  14137.                             bool priced = ((item*)items.spr(j))->PriceIndex >-1;
  14138.                            
  14139.                             if((((item*)items.spr(j))->pickup & ipTIMER && ((item*)items.spr(j))->clk2 >= 32)
  14140.                                     || (get_bit(quest_rules,qr_BRANGPICKUP) && !priced))
  14141.                             {
  14142.                                 if(itemsbuf[items.spr(j)->id].collect_script)
  14143.                                 {
  14144.                                     ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[items.spr(j)->id].collect_script, items.spr(j)->id & 0xFFF);
  14145.                                 }
  14146.                                
  14147.                                 //getitem(items.spr(j)->id);
  14148.                                 //items.del(j);
  14149.                                 Link.checkitems(j);
  14150.                                 //--j;
  14151.                             }
  14152.                         }
  14153.                     }
  14154.                 }
  14155.             }
  14156.         }
  14157.     }
  14158. }
  14159.  
  14160. void dragging_item()
  14161. {
  14162.     if(get_bit(quest_rules,qr_Z3BRANG_HSHOT))
  14163.     {
  14164.         for(int i=0; i<Lwpns.Count(); i++)
  14165.         {
  14166.             weapon *w = (weapon*)Lwpns.spr(i);
  14167.            
  14168.             if(w->id == wBrang || w->id==wHookshot)
  14169.             {
  14170.                 if(w->dragging>=0 && w->dragging<items.Count())
  14171.                 {
  14172.                     items.spr(w->dragging)->x=w->x;
  14173.                     items.spr(w->dragging)->y=w->y;
  14174.                    
  14175.                     // Drag the Fairy enemy as well as the Fairy item
  14176.                     int id = items.spr(w->dragging)->id;
  14177.                    
  14178.                     if(itemsbuf[id].family ==itype_fairy && itemsbuf[id].misc3)
  14179.                     {
  14180.                         movefairy2(w->x,w->y,items.spr(w->dragging)->misc);
  14181.                     }
  14182.                 }
  14183.             }
  14184.         }
  14185.     }
  14186. }
  14187.  
  14188. int more_carried_items()
  14189. {
  14190.     int hasmorecarries = 0;
  14191.    
  14192.     for(int i=0; i<items.Count(); i++)
  14193.     {
  14194.         if(((item*)items.spr(i))->pickup & ipENEMY)
  14195.         {
  14196.             hasmorecarries++;
  14197.         }
  14198.     }
  14199.    
  14200.     return hasmorecarries;
  14201. }
  14202.  
  14203. // messy code to do the enemy-carrying-the-item thing
  14204. void roaming_item()
  14205. {
  14206.     if(hasitem<2 || !loaded_enemies)
  14207.         return;
  14208.    
  14209.     // All enemies already dead upon entering a room?
  14210.     if(guys.Count()==0)
  14211.     {
  14212.         return;
  14213.     }
  14214.    
  14215.     // Lost track of the carrier?
  14216.     if(guycarryingitem<0 || guycarryingitem>=guys.Count() ||
  14217.        !((enemy*)guys.spr(guycarryingitem))->itemguy)
  14218.     {
  14219.         guycarryingitem=-1;
  14220.         for(int j=0; j<guys.Count(); j++)
  14221.         {
  14222.             if(((enemy*)guys.spr(j))->itemguy)
  14223.             {
  14224.                 guycarryingitem=j;
  14225.                 break;
  14226.             }
  14227.         }
  14228.     }
  14229.    
  14230.     if(hasitem&4)
  14231.     {
  14232.         guycarryingitem = -1;
  14233.        
  14234.         for(int i=0; i<guys.Count(); i++)
  14235.         {
  14236.             if(((enemy*)guys.spr(i))->itemguy)
  14237.             {
  14238.                 guycarryingitem = i;
  14239.             }
  14240.         }
  14241.        
  14242.         if(guycarryingitem == -1)                                      //This happens when "default enemies" such as
  14243.         {
  14244.             return;                                               //eSHOOTFBALL are alive but enemies from the list
  14245.         }                                                       //are not. Defer to LinkClass::checkspecial().
  14246.        
  14247.         int Item=tmpscr->item;
  14248.        
  14249.         hasitem &= ~4;
  14250.        
  14251.         if(!getmapflag(mITEM) && (tmpscr->hasitem != 0))
  14252.         {
  14253.             additem(0,0,Item,ipENEMY+ipONETIME+ipBIGRANGE
  14254.                     + (((tmpscr->flags3&fHOLDITEM) || (itemsbuf[Item].family==itype_triforcepiece)) ? ipHOLDUP : 0)
  14255.                    );
  14256.             hasitem |= 2;
  14257.         }
  14258.         else
  14259.         {
  14260.             return;
  14261.         }
  14262.     }
  14263.    
  14264.     for(int i=0; i<items.Count(); i++)
  14265.     {
  14266.         if(((item*)items.spr(i))->pickup&ipENEMY)
  14267.         {
  14268.             if(get_bit(quest_rules,qr_HIDECARRIEDITEMS))
  14269.             {
  14270.                 items.spr(i)->x = -128; // Awfully inelegant, innit?
  14271.                 items.spr(i)->y = -128;
  14272.             }
  14273.             else if(guycarryingitem>=0 && guycarryingitem<guys.Count())
  14274.             {
  14275.                 items.spr(i)->x = guys.spr(guycarryingitem)->x;
  14276.                 items.spr(i)->y = guys.spr(guycarryingitem)->y - 2;
  14277.             }
  14278.         }
  14279.     }
  14280. }
  14281.  
  14282. const char *old_guy_string[OLDMAXGUYS] =
  14283. {
  14284.     "(None)","Abei","Ama","Merchant","Moblin","Fire","Fairy","Goriya","Zelda","Abei 2","Empty","","","","","","","","","",
  14285.     // 020
  14286.     "Octorok (L1, Slow)","Octorok (L2, Slow)","Octorok (L1, Fast)","Octorok (L2, Fast)","Tektite (L1)",
  14287.     // 025
  14288.     "Tektite (L2)","Leever (L1)","Leever (L2)","Moblin (L1)","Moblin (L2)",
  14289.     // 030
  14290.     "Lynel (L1)","Lynel (L2)","Peahat (L1)","Zora","Rock",
  14291.     // 035
  14292.     "Ghini (L1, Normal)","Ghini (L1, Phantom)","Armos","Keese (CSet 7)","Keese (CSet 8)",
  14293.     // 040
  14294.     "Keese (CSet 9)","Stalfos (L1)","Gel (L1, Normal)","Zol (L1, Normal)","Rope (L1)",
  14295.     // 045
  14296.     "Goriya (L1)","Goriya (L2)","Trap (4-Way)","Wall Master","Darknut (L1)",
  14297.     // 050
  14298.     "Darknut (L2)","Bubble (Sword, Temporary Disabling)","Vire (Normal)","Like Like","Gibdo",
  14299.     // 055
  14300.     "Pols Voice (Arrow)","Wizzrobe (Teleporting)","Wizzrobe (Floating)","Aquamentus (Facing Left)","Moldorm",
  14301.     // 060
  14302.     "Dodongo","Manhandla (L1)","Gleeok (1 Head)","Gleeok (2 Heads)","Gleeok (3 Heads)",
  14303.     // 065
  14304.     "Gleeok (4 Heads)","Digdogger (1 Kid)","Digdogger (3 Kids)","Digdogger Kid (1)","Digdogger Kid (2)",
  14305.     // 070
  14306.     "Digdogger Kid (3)","Digdogger Kid (4)","Gohma (L1)","Gohma (L2)","Lanmola (L1)",
  14307.     // 075
  14308.     "Lanmola (L2)","Patra (L1, Big Circle)","Patra (L1, Oval)","Ganon","Stalfos (L2)",
  14309.     // 080
  14310.     "Rope (L2)","Bubble (Sword, Permanent Disabling)","Bubble (Sword, Re-enabling)","Shooter (Fireball)","Item Fairy ",
  14311.     // 085
  14312.     "Fire","Octorok (Magic)", "Darknut (Death Knight)", "Gel (L1, Tribble)", "Zol (L1, Tribble)",
  14313.     // 090
  14314.     "Keese (Tribble)", "Vire (Tribble)", "Darknut (Splitting)", "Aquamentus (Facing Right)", "Manhandla (L2)",
  14315.     // 095
  14316.     "Trap (Horizontal, Line of Sight)", "Trap (Vertical, Line of Sight)", "Trap (Horizontal, Constant)", "Trap (Vertical, Constant)", "Wizzrobe (Fire)",
  14317.     // 100
  14318.     "Wizzrobe (Wind)", "Ceiling Master ", "Floor Master ", "Patra (BS Zelda)", "Patra (L2)",
  14319.     // 105
  14320.     "Patra (L3)", "Bat", "Wizzrobe (Bat)", "Wizzrobe (Bat 2) ", "Gleeok (Fire, 1 Head)",
  14321.     // 110
  14322.     "Gleeok (Fire, 2 Heads)",  "Gleeok (Fire, 3 Heads)","Gleeok (Fire, 4 Heads)", "Wizzrobe (Mirror)", "Dodongo (BS Zelda)",
  14323.     // 115
  14324.     "Dodongo (Fire) ","Trigger", "Bubble (Item, Temporary Disabling)", "Bubble (Item, Permanent Disabling)", "Bubble (Item, Re-enabling)",
  14325.     // 120
  14326.     "Stalfos (L3)", "Gohma (L3)", "Gohma (L4)", "NPC 1 (Standing) ", "NPC 2 (Standing) ",
  14327.     // 125
  14328.     "NPC 3 (Standing) ", "NPC 4 (Standing) ", "NPC 5 (Standing) ", "NPC 6 (Standing) ", "NPC 1 (Walking) ",
  14329.     // 130
  14330.     "NPC 2 (Walking) ", "NPC 3 (Walking) ", "NPC 4 (Walking) ", "NPC 5 (Walking) ", "NPC 6 (Walking) ",
  14331.     // 135
  14332.     "Boulder", "Goriya (L3)", "Leever (L3)", "Octorok (L3, Slow)", "Octorok (L3, Fast)",
  14333.     // 140
  14334.     "Octorok (L4, Slow)", "Octorok (L4, Fast)", "Trap (8-Way) ", "Trap (Diagonal) ", "Trap (/, Constant) ",
  14335.     // 145
  14336.     "Trap (/, Line of Sight) ", "Trap (\\, Constant) ", "Trap (\\, Line of Sight) ", "Trap (CW, Constant) ", "Trap (CW, Line of Sight) ",
  14337.     // 150
  14338.     "Trap (CCW, Constant) ", "Trap (CCW, Line of Sight) ", "Wizzrobe (Summoner)", "Wizzrobe (Ice) ", "Shooter (Magic)",
  14339.     // 155
  14340.     "Shooter (Rock)", "Shooter (Spear)", "Shooter (Sword)", "Shooter (Fire)", "Shooter (Fire 2)",
  14341.     // 160
  14342.     "Bombchu", "Gel (L2, Normal)", "Zol (L2, Normal)", "Gel (L2, Tribble)", "Zol (L2, Tribble)",
  14343.     // 165
  14344.     "Tektite (L3) ", "Spinning Tile (Combo)", "Spinning Tile (Enemy Sprite)", "Lynel (L3) ", "Peahat (L2) ",
  14345.     // 170
  14346.     "Pols Voice (Magic) ", "Pols Voice (Whistle) ", "Darknut (Mirror) ", "Ghini (L2, Fire) ", "Ghini (L2, Magic) ",
  14347.     // 175
  14348.     "Grappler Bug (HP) ", "Grappler Bug (MP) "
  14349. };
  14350.  
  14351. /*** end of guys.cc ***/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement