Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "hydra.h"
  2. #include "../game.h"
  3. #include "../hero.h"
  4. #include <stdlib.h>
  5. #include <math.h>
  6.  
  7. const double PI = 3.14159;
  8.  
  9. double headRot = 0;
  10.  
  11. void hydraStep(Hydra* h);
  12. void hydraDraw(Hydra* h);
  13.  
  14. void hydraDestroy(Hydra* h);
  15.  
  16. void hydraheadStep(Hydrahead* h);
  17. void hydraheadDraw(Hydrahead* h);
  18.  
  19. void hydragoopStep(Hydragoop* h);
  20. void hydragoopDraw(Hydragoop* h);
  21.  
  22. void hydrarockStep(Hydrarock* h);
  23. void hydrarockDraw(Hydrarock* h);
  24.  
  25. void hydrashockStep(Hydrashock* h);
  26. void hydrashockDraw(Hydrashock* h);
  27.  
  28. double getHydraX(Hydrahead* h);
  29. double getHydraY(Hydrahead* h);
  30.  
  31. Mask getHydraMask(Hydra* h);
  32. int checkWeaponCollision(Mask m);
  33.  
  34. double lengthdir_x(double ang, double len);
  35. double lengthdir_y(double ang, double len);
  36.  
  37. void setHeadState(int headid, int state);
  38.  
  39.  
  40. //#hydra
  41. void createHydra(int x)
  42. {
  43.         PHL_FreeSurface(images[imgBoss]);
  44.         images[imgBoss] = PHL_LoadQDA("lboss01.bmp");
  45.        
  46.         int i;
  47.         for (i = 4; i < MAX_ENEMIES; i++) {
  48.                 if (enemies[i] == NULL) {
  49.                         setBossRoom();
  50.                        
  51.                         Enemy* e = malloc(sizeof *e);
  52.                         Hydra* h = malloc(sizeof *h);
  53.                         h->id = i;
  54.                        
  55.                         h->hp = 10;
  56.                         //h->hp = 1;
  57.                         h->blink = 0;
  58.                        
  59.                         h->x = x;
  60.                         h->y = -64;
  61.                        
  62.                         h->hsp = 0;
  63.                         h->vsp = 0;
  64.                        
  65.                         h->imageIndex = 0;
  66.                        
  67.                         h->state = 0;
  68.                         h->timer = 0;
  69.                        
  70.                         h->patternCounter = 0;
  71.                        
  72.                         h->onground = 0;
  73.                         h->noheads = 0;
  74.                        
  75.                         e->data = h;
  76.                         e->enemyStep = hydraStep;
  77.                         e->enemyDraw = hydraDraw;
  78.                         e->type = 47;
  79.                        
  80.                         enemies[i] = e;
  81.                                                
  82.                         h->headid[0] = createHydrahead(-1, 0, i);
  83.                         h->headid[1] = createHydrahead(1, 0, i);
  84.                         h->headid[2] = createHydrahead(1, 1, i);
  85.                         h->headid[3] = createHydrahead(-1, 1, i);
  86.                        
  87.                         i = MAX_ENEMIES;
  88.                 }
  89.         }
  90. }
  91.  
  92. void hydraStep(Hydra* h)
  93. {      
  94.         double grav = 0.2;
  95.         double fric = 0.1;
  96.        
  97.         //Death
  98.         if (h->state == 6) {
  99.                 h->y += 0.2;
  100.                
  101.                 h->timer -= 1;
  102.                 h->blink -= 1;
  103.                
  104.                 if (h->timer % 12 == 0) {
  105.                         createEffect(2, h->x - 64 + (rand() % 128) - 32, h->y - 64 + (rand() % 128));
  106.                 }
  107.                
  108.                 if (h->timer <= 0) {
  109.                         hydraDestroy(h);
  110.                 }
  111.         }
  112.         else{  
  113.                 //Setup Mask
  114.                 Mask mask = getHydraMask(h);
  115.                
  116.                 //States with hydra heads
  117.                 if (h->noheads == 0) {         
  118.                         //Fall in intro
  119.                         if (h->state == 0) {
  120.                                 h->hsp = 0;
  121.                                 h->timer += 1;
  122.                                 if (h->timer >= 50) {
  123.                                         h->timer = 50;                 
  124.                                         h->imageIndex = 2;
  125.                                        
  126.                                         if (h->onground == 1) {
  127.                                                 h->state = 1;
  128.                                                 h->timer = 0;
  129.                                         }
  130.                                 }else{
  131.                                         grav = 0;
  132.                                 }
  133.                         }
  134.                        
  135.                         //Wait/Pattern activate
  136.                         else if (h->state == 1)
  137.                         {                      
  138.                                 h->timer += 1;
  139.                                
  140.                                 //Stop speed animation
  141.                                 if (h->timer >= 120) {                                 
  142.                                         int patternSize = 9;
  143.                                         int pattern[9] = {4, 0, 4, 1, 4, 2, 4, 3, 2};
  144.                                        
  145.                                         //Head seizure
  146.                                         if (pattern[h->patternCounter] == 4) {
  147.                                                 h->state = 4;
  148.                                                 h->timer = 0;
  149.                                         }
  150.                                         //Small hop
  151.                                         if (pattern[h->patternCounter] == 0) {
  152.                                                 h->state = 2;
  153.                                                 h->timer = 0;                                  
  154.                                         }
  155.                                        
  156.                                         //Goop
  157.                                         if (pattern[h->patternCounter] == 1) {
  158.                                                 h->timer = -120;
  159.                                                 setHeadState(h->headid[0], 2);
  160.                                                 setHeadState(h->headid[1], 2);
  161.                                         }
  162.                                        
  163.                                         //Big Hop
  164.                                         if (pattern[h->patternCounter] == 2) {
  165.                                                 h->state = 3;
  166.                                                 h->timer = 0;
  167.                                         }
  168.                                        
  169.                                         //Electricity
  170.                                         if (pattern[h->patternCounter] == 3) {
  171.                                                 h->timer = -40;
  172.                                                 setHeadState(h->headid[2], 3);
  173.                                                 setHeadState(h->headid[3], 3);
  174.                                         }
  175.                                        
  176.                                         h->patternCounter += 1;
  177.                                         if (h->patternCounter >= patternSize) {
  178.                                                 h->patternCounter = 0;
  179.                                         }
  180.                                 }
  181.                         }
  182.                        
  183.                         //Head seizure state
  184.                         else if (h->state == 4) {                      
  185.                                 //Speed up head animation
  186.                                 if (h->timer == 0) {
  187.                                         setHeadState(h->headid[0], 1);
  188.                                         setHeadState(h->headid[1], 1);
  189.                                         setHeadState(h->headid[2], 1);
  190.                                         setHeadState(h->headid[3], 1);
  191.                                 }
  192.                                
  193.                                 h->timer += 1;
  194.                                
  195.                                 //Stop speed animation
  196.                                 if (h->timer == 120) {                         
  197.                                         setHeadState(h->headid[0], 0);
  198.                                         setHeadState(h->headid[1], 0);
  199.                                         setHeadState(h->headid[2], 0);
  200.                                         setHeadState(h->headid[3], 0);
  201.                                        
  202.                                         //Pattern
  203.                                         h->state = 1;
  204.                                         h->timer = 120;
  205.                                 }
  206.                         }
  207.                        
  208.                         //Switch to noheads mode
  209.                         if (h->onground == 1 &&
  210.                                 enemies[h->headid[0]] == NULL &&
  211.                                 enemies[h->headid[1]] == NULL &&
  212.                                 enemies[h->headid[2]] == NULL &&
  213.                                 enemies[h->headid[3]] == NULL)
  214.                         {
  215.                                 h->noheads = 1;
  216.                                 h->state = 1;
  217.                                 h->timer = -15;
  218.                                 h->patternCounter = 0;
  219.                         }
  220.                 }
  221.                
  222.                 //States without hydra heads
  223.                 else{                          
  224.                         //Wait/pattern activate
  225.                         if (h->state == 1) {
  226.                                 h->timer += 1;
  227.                                
  228.                                 if (h->timer >= 0) {
  229.                                         int patternSize = 3;
  230.                                         int pattern[3] = {0, 0, 2};
  231.                                        
  232.                                         //Small hop
  233.                                         if (pattern[h->patternCounter] == 0) {
  234.                                                 h->state = 2;
  235.                                                 h->timer = 0;                                  
  236.                                         }
  237.                                        
  238.                                         //Big Hop
  239.                                         if (pattern[h->patternCounter] == 2) {
  240.                                                 h->state = 3;
  241.                                                 h->timer = 0;
  242.                                         }
  243.                                        
  244.                                         h->patternCounter += 1;
  245.                                         if (h->patternCounter >= patternSize) {
  246.                                                 h->patternCounter = 0;
  247.                                         }
  248.                                 }
  249.                         }
  250.                 }
  251.                
  252.                 //States used by both modes
  253.                 {
  254.                         //Small hop
  255.                         if (h->state == 2) {                   
  256.                                 //Setup
  257.                                 if (h->timer == 0) {
  258.                                         h->vsp = -2;
  259.                                         h->onground = 0;
  260.                                         h->hsp = 2.5;
  261.                                         if (herox < h->x) {
  262.                                                 h->hsp *= -1;
  263.                                         }
  264.                                 }
  265.                                
  266.                                 h->timer += 1;
  267.                                
  268.                                 if (h->onground == 1) {
  269.                                         if (h->noheads == 0 || h->hsp == 0) {
  270.                                                 h->state = 1;
  271.                                                 h->timer = 0;
  272.                                         }
  273.                                 }
  274.                         }
  275.                        
  276.                         //Large Hop
  277.                         else if (h->state == 3) {
  278.                                 h->hsp = 0;
  279.                                
  280.                                 //Setup
  281.                                 if (h->timer == 0) {
  282.                                         h->timer = 1;
  283.                                         if (h->noheads == 0) {
  284.                                                 h->vsp = -8;
  285.                                         }else{
  286.                                                 h->vsp = -5;
  287.                                         }
  288.                                         h->onground = 0;
  289.                                 }
  290.                                
  291.                                 if (h->onground == 1) {
  292.                                         h->timer += 1;
  293.                                        
  294.                                         if (h->timer % 20 == 0) {
  295.                                                 createHydrarock();
  296.                                         }
  297.                                        
  298.                                         if (h->timer >= 220) {
  299.                                                 h->state = 1;
  300.                                                 h->timer = -15;
  301.                                         }
  302.                                 }
  303.                         }
  304.                 }
  305.                        
  306.                 //Animate
  307.                 {
  308.                         if (h->onground == 1) {
  309.                                 h->imageIndex += 0.1;
  310.                                 if (h->imageIndex >= 2) {
  311.                                         h->imageIndex -= 2;
  312.                                 }
  313.                         }else{
  314.                                 if (h->vsp < 0) {
  315.                                         h->imageIndex = 3;
  316.                                 }
  317.                                 else {
  318.                                         h->imageIndex = 2;
  319.                                 }
  320.                         }
  321.                        
  322.                         //Blink
  323.                         if (h->blink > 0) {
  324.                                 h->blink -= 1;
  325.                         }
  326.                 }
  327.                        
  328.                 //Movement
  329.                 {
  330.                         //Horizontal
  331.                         if (h->hsp != 0) {
  332.                                 h->x += h->hsp;
  333.                                 mask = getHydraMask(h);
  334.                                
  335.                                 PHL_Rect collide = getTileCollision(1, mask);
  336.                                 if (collide.x != -1) {
  337.                                         int dir = 1;
  338.                                         if (h->hsp < 0) {
  339.                                                 dir = -1;
  340.                                         }
  341.                                         h->x = collide.x + 20 - ((20 + (mask.w / 2)) * dir);
  342.                                        
  343.                                         h->hsp *= -1;
  344.                                 }
  345.                         }
  346.                        
  347.                         //Friction
  348.                         {
  349.                                 if (h->onground == 1) {
  350.                                         if (h->hsp > 0) {
  351.                                                 h->hsp -= fric;
  352.                                                 if (h->hsp < 0) {
  353.                                                         h->hsp = 0;
  354.                                                 }
  355.                                         }
  356.                                         if (h->hsp < 0) {
  357.                                                 h->hsp += fric;
  358.                                                 if (h->hsp > 0) {
  359.                                                         h->hsp = 0;
  360.                                                 }
  361.                                         }
  362.                                 }
  363.                         }
  364.                        
  365.                         //Vertical
  366.                         {
  367.                                 int maxVsp = 9;
  368.                                
  369.                                 if (h->onground == 0) {
  370.                                         h->y += h->vsp;
  371.                                         h->vsp += grav;
  372.                                         mask = getHydraMask(h);
  373.                                        
  374.                                         //Limit vsp
  375.                                         {
  376.                                                 if (h->vsp > maxVsp) {
  377.                                                         h->vsp = maxVsp;
  378.                                                 }
  379.                                         }
  380.                                        
  381.                                         //Collide with floor
  382.                                         {
  383.                                                 PHL_Rect collide = getTileCollision(1, mask);
  384.                                                 if (collide.x != -1) {
  385.                                                         h->y = collide.y - 64;
  386.                                                         h->vsp = 0;
  387.                                                         h->onground = 1;
  388.                                                         PHL_PlaySound(sounds[sndHit04], CHN_ENEMIES);
  389.                                                         quakeTimer = 30;
  390.                                                         createEffectExtra(3, h->x - 30, h->y + 32, -1, 0, 0);
  391.                                                         createEffectExtra(3, h->x - 10, h->y + 32, 1, 0, 0);
  392.                                                 }
  393.                                         }
  394.                                 }
  395.                         }
  396.                                
  397.                 }
  398.                
  399.                 //Update mask
  400.                 mask = getHydraMask(h);
  401.                
  402.                 //Hero Collision
  403.                 {
  404.                         if (checkCollision(mask, getHeroMask()) == 1) {
  405.                                 heroHit(25, h->x);
  406.                         }
  407.                 }
  408.                        
  409.                 //Weapon Collision
  410.                 {
  411.                         int wid = checkWeaponCollision(mask);
  412.                         if (wid != -1) {
  413.                                 //Pushed back
  414.                                 if (h->noheads == 0) {
  415.                                         h->hsp = weapons[wid]->dir;
  416.                                         PHL_PlaySound(sounds[sndPi05], CHN_ENEMIES);
  417.                                 }else{
  418.                                         h->hp -= 1;
  419.                                         h->blink = 15;
  420.                                 }
  421.                                 weaponHit(weapons[wid]);
  422.                                 //Die
  423.                                 if (h->hp <= 0) {
  424.                                         h->state = 6;
  425.                                         h->timer = 180;
  426.                                         h->blink = 200;
  427.                                 }
  428.                                
  429.                         }
  430.                 }
  431.         }
  432.        
  433. }
  434.  
  435. void hydraDraw(Hydra* h)
  436. {
  437.         if (h->blink % 2 == 0) {       
  438.                 int cropX = (int)h->imageIndex * 128;
  439.                 int cropY = 128;
  440.                
  441.                 if (h->noheads == 1) {
  442.                         cropY += 128;
  443.                 }
  444.                
  445.                 PHL_DrawSurfacePart(h->x - 64, h->y - 64, cropX, cropY, 128, 128, images[imgBoss]);            
  446.         }
  447. }
  448.  
  449. void hydraDestroy(Hydra* h)
  450. {
  451.         enemyDestroy(h->id);
  452.         bossDefeatedFlag = 1;
  453.         roomSecret = 1;
  454.  
  455.         PHL_StopMusic();
  456. }
  457.  
  458. Mask getHydraMask(Hydra* h)
  459. {
  460.         Mask mask;
  461.        
  462.         mask.unused = mask.circle = 0;
  463.         mask.w = 84;
  464.         mask.h = 84;
  465.         mask.x = h->x - (mask.w / 2);
  466.         mask.y = h->y - 64 + (128 - mask.h);
  467.        
  468.         return mask;
  469. }
  470.  
  471. //#heads
  472. int createHydrahead(int dir, int position, int bodyid)
  473. {
  474.         int result = -1;
  475.        
  476.         int i;
  477.         for (i = 0; i < MAX_ENEMIES; i++) {
  478.                 if (enemies[i] == NULL) {
  479.                         Enemy* e = malloc(sizeof *e);
  480.                         Hydrahead* h = malloc(sizeof *h);
  481.                        
  482.                         h->id = i;
  483.                         result = i;
  484.                        
  485.                         h->hp = 25;
  486.                         //h->hp = 1;
  487.                         h->blink = 0;
  488.                        
  489.                         h->dir = dir;
  490.                         h->position = position;
  491.                        
  492.                         h->imageIndex = 0;
  493.                        
  494.                         h->neckRot = 0;
  495.                         if (position != 0) {
  496.                                 h->neckRot -= 45;
  497.                         }
  498.                        
  499.                         h->state = 0;
  500.                         h->timer = 0;
  501.                         h->counter = 0;
  502.                        
  503.                         h->bodyid = bodyid;
  504.                        
  505.                         int a;
  506.                         for (a = 0; a < 7; a++) {
  507.                                 h->bodyposX[a] = 0;
  508.                                 h->bodyposY[a] = 0;
  509.                         }
  510.                        
  511.                         e->data = h;
  512.                         e->enemyStep = hydraheadStep;
  513.                         e->enemyDraw = hydraheadDraw;
  514.                         e->type = -1;
  515.                        
  516.                         enemies[i] = e;
  517.                         i = MAX_ENEMIES;
  518.                 }
  519.         }
  520.        
  521.         return result;
  522. }
  523.  
  524. void hydraheadStep(Hydrahead* h)
  525. {
  526.         char dead = 0;
  527.        
  528.         //Animate
  529.         {
  530.                 h->imageIndex += 0.1;
  531.                 if (h->imageIndex >= 2) {
  532.                         h->imageIndex -= 2;
  533.                 }
  534.                
  535.                 if (h->blink > 0) {
  536.                         h->blink -= 1;
  537.                 }
  538.                
  539.                 h->neckRot += 2;
  540.                 if (h->neckRot >= 360) {
  541.                         h->neckRot -= 360;
  542.                 }
  543.         }
  544.        
  545.         //States
  546.         {
  547.                 //Death
  548.                 if (h->state == 4) {
  549.                         h->timer += 1;
  550.                         if (h->timer % 6 == 0) {
  551.                                 createEffect(2, h->bodyposX[6 - h->counter] - 32, h->bodyposY[6 - h->counter] - 32);
  552.                                 h->counter += 1;
  553.                         }
  554.                        
  555.                         if (h->counter >= 7) {
  556.                                 dead = 1;
  557.                         }
  558.                 }
  559.                 else{
  560.                         if (h->state == 0) {
  561.                                 //Do nothing special
  562.                         }
  563.                
  564.                         //Fast movements
  565.                         else if (h->state == 1) {
  566.                                 h->neckRot += 2;
  567.                         }
  568.                
  569.                         //Shoot goop
  570.                         else if (h->state == 2) {
  571.                                 h->neckRot += 2;
  572.                                 h->timer += 1;
  573.                                
  574.                                 //Create Goop
  575.                                 if (h->timer % 15 == 0) {                              
  576.                                         int ghsp = -4 + (rand() % 9),
  577.                                                 gvsp = -6;
  578.                                        
  579.                                         createHydragoop(h->bodyposX[6], h->bodyposY[6], ghsp, gvsp);
  580.                                 }
  581.                                
  582.                                 if (h->timer >= 120) {
  583.                                         h->state = 0;
  584.                                 }
  585.                         }
  586.                
  587.                         //Shoot electricity
  588.                         else if (h->state == 3) {
  589.                                 if (h->timer == 0) {
  590.                                         h->timer = 1;
  591.                                 }
  592.                        
  593.                                 if (h->timer % 20 == 0) {
  594.                                         if (h->counter == 0) {
  595.                                                 createHydrashock(h->bodyposX[6] + (70 * h->dir), h->bodyposY[6] + 20);
  596.                                         }
  597.                                         h->neckRot -= 2;
  598.                                         h->counter += 1;
  599.                                         if (h->counter >= 20) {
  600.                                                 h->counter = 0;
  601.                                                 h->timer += 1;
  602.                                         }
  603.                                 }else{
  604.                                         h->neckRot += 2;
  605.                                         h->timer += 1;
  606.                                 }              
  607.                                
  608.                                 if (h->timer > 80) {
  609.                                         h->state = 0;
  610.                                         /*
  611.                                         Hydra* body = enemies[h->bodyid]->data;
  612.                                         body->state = 1;
  613.                                         body->timer = 239;
  614.                                         */
  615.                                 }
  616.                                
  617.                         }
  618.                        
  619.                         Mask mask;
  620.                         mask.circle = mask.unused = 0;
  621.                        
  622.                         //Collide with player
  623.                         {              
  624.                                 int i;
  625.                                 for (i = 0; i < 7; i+=2) {
  626.                                         //Setup mask
  627.                                         {
  628.                                                 mask.w = 48;
  629.                                                 mask.h = 48;
  630.                                                
  631.                                                 //Head
  632.                                                 if (i == 6) {
  633.                                                         mask.w = 60;
  634.                                                         mask.h = 36;
  635.                                                 }
  636.                                                
  637.                                                 mask.x = h->bodyposX[i] - (mask.w / 2);
  638.                                                 mask.y = h->bodyposY[i] - (mask.h / 2);
  639.                                         }
  640.                                        
  641.                                         //Collide
  642.                                         if (checkCollision(getHeroMask(), mask) == 1) {
  643.                                                 heroHit(25, getHydraX(h));
  644.                                         }                      
  645.                                 }
  646.                         }
  647.                        
  648.                         //Weapon collision
  649.                         {
  650.                                 //Mask should still be on the head
  651.                                 int wid = checkWeaponCollision(mask);
  652.                                 if (wid != -1) {
  653.                                         h->blink = 15;
  654.                                         h->hp -= 1;
  655.                                         weaponHit(weapons[wid]);
  656.                                        
  657.                                         if (h->hp <= 0) {
  658.                                                 h->state = 4;
  659.                                                 h->timer = 0;
  660.                                                 h->counter = 0;
  661.                                         }
  662.                                 }
  663.                         }
  664.                        
  665.                        
  666.                 }
  667.        
  668.         }
  669.        
  670.         //Destroy object
  671.         if (dead == 1) {
  672.                 enemyDestroy(h->id);
  673.         }
  674. }
  675.  
  676. void hydraheadDraw(Hydrahead* h)
  677. {
  678.         /*
  679.         char c[10];
  680.         sprintf(c, "%02d", h->timer);
  681.         PHL_DrawTextBold(c, h->bodyposX[6], 0, 0);
  682.         */
  683.        
  684.         h->bodyposX[0] = getHydraX(h) + 20;
  685.         h->bodyposY[0] = getHydraY(h);
  686.                
  687.         double drawX = getHydraX(h) + 20;
  688.         double drawY = getHydraY(h);
  689.        
  690.         int dis = 24;
  691.         int angle = -25;
  692.                
  693.         if (h->position == 1) {
  694.                 angle = -60;
  695.                        
  696.                 drawX -= 5;
  697.                 drawY -= 20;
  698.         }
  699.                
  700.         int i;
  701.         for (i = 0; i < 7; i++) {
  702.                 double wavlen = sin((h->neckRot + (45 * i)) * PI / 180);
  703.                
  704.                 double incang = 45;
  705.                        
  706.                 if (h->position != 0) {
  707.                         incang = 45;
  708.                 }
  709.                        
  710.                 if (i == 6) {
  711.                         //incang += 15;
  712.                         incang = 50;
  713.                                
  714.                         if (h->position == 1) {
  715.                                 incang = 80;
  716.                         }
  717.                 }
  718.                
  719.                 drawX += lengthdir_x(angle + (incang * wavlen), dis);
  720.                 drawY += lengthdir_y(angle + (incang * wavlen), dis);
  721.                        
  722.                 h->bodyposX[i] = drawX;
  723.                 h->bodyposY[i] = drawY;
  724.                        
  725.                 if (h->dir == -1) {
  726.                         double difference = h->bodyposX[i] - getHydraX(h);
  727.                         h->bodyposX[i] = getHydraX(h) - difference;
  728.                 }
  729.                        
  730.                 if (h->blink % 2 == 0) {
  731.                         if (h->state != 4 || (6 - h->counter >= i)) {
  732.                                 if (i != 6) {
  733.                                         int cropX = 0;
  734.                                        
  735.                                         if (h->dir == -1) {
  736.                                                 cropX += 64;
  737.                                         }
  738.                                        
  739.                                         PHL_DrawSurfacePart(h->bodyposX[i] - 32, h->bodyposY[i] - 32, cropX, 64, 64, 64, images[imgBoss]);
  740.                                 }else{
  741.                                         int cropX = 0;
  742.                                        
  743.                                         if (h->dir == -1) {
  744.                                                 cropX += 320;
  745.                                         }
  746.                                        
  747.                                         cropX += (int)h->imageIndex * 80;
  748.                                        
  749.                                         PHL_DrawSurfacePart(h->bodyposX[i] - 40, h->bodyposY[i] - 32, cropX, 0, 80, 64, images[imgBoss]);
  750.                                 }
  751.                         }
  752.                 }
  753.         }
  754.        
  755. }
  756.  
  757. int checkWeaponCollision(Mask m)
  758. {
  759.         int i;
  760.         for (i = 0; i < MAX_WEAPONS; i++) {
  761.                 if (weapons[i] != NULL) {
  762.                         if (weapons[i]->cooldown == 0) {
  763.                                 if (checkCollision(weapons[i]->weaponMask, m) == 1) {
  764.                                         return i;
  765.                                 }
  766.                         }
  767.                 }
  768.         }
  769.        
  770.         return -1;
  771. }
  772.  
  773. double lengthdir_x(double ang, double len)
  774. {
  775.         return cos(ang * PI / 180) * len;
  776. }
  777.  
  778. double lengthdir_y(double ang, double len)
  779. {
  780.         return sin(ang * PI / 180) * len;
  781. }
  782.  
  783. double getHydraX(Hydrahead* h)
  784. {
  785.         if (enemies[h->bodyid] != NULL) {
  786.                 Hydra* hbody = enemies[h->bodyid]->data;
  787.                 return hbody->x;
  788.         }
  789.        
  790.         return -1;
  791. }
  792.  
  793. double getHydraY(Hydrahead* h)
  794. {
  795.         if (enemies[h->bodyid] != NULL) {
  796.                 Hydra* hbody = enemies[h->bodyid]->data;
  797.                 return hbody->y;
  798.         }
  799.        
  800.         return -1;
  801. }
  802.  
  803. void setHeadState(int headid, int state)
  804. {
  805.         if (enemies[headid] != NULL) {
  806.                 Hydrahead* h = enemies[headid]->data;
  807.                 if (h->state != 4) {
  808.                         h->state = state;
  809.                         h->timer = 0;
  810.                         h->counter = 0;
  811.                 }
  812.         }
  813. }
  814.  
  815. //#goop
  816. void createHydragoop(int x, int y, int hsp, int vsp)
  817. {
  818.         int i;
  819.         for (i = 0; i < MAX_ENEMIES; i++) {
  820.                 if (enemies[i] == NULL) {
  821.                         Enemy* e = malloc(sizeof *e);
  822.                         Hydragoop* h = malloc(sizeof *h);
  823.                         h->id = i;
  824.                        
  825.                         h->x = x;
  826.                         h->y = y;
  827.                        
  828.                         h->hsp = hsp;
  829.                         h->vsp = vsp;
  830.                        
  831.                         h->inwall = 0;
  832.                         h->bounce = 0;
  833.                        
  834.                         h->imageIndex = 0;
  835.                        
  836.                         e->data = h;
  837.                         e->enemyStep = hydragoopStep;
  838.                         e->enemyDraw = hydragoopDraw;
  839.                         e->type = -1;
  840.                        
  841.                         enemies[i] = e;                
  842.                         i = MAX_ENEMIES;
  843.                        
  844.                         PHL_PlaySound(sounds[sndPi06], CHN_ENEMIES);
  845.                 }
  846.         }
  847. }
  848.  
  849. void hydragoopStep(Hydragoop* h)
  850. {
  851.         char dead = 0;
  852.        
  853.         //Animate
  854.         {
  855.                 h->imageIndex += 0.16;
  856.                 if (h->imageIndex >= 3) {
  857.                         h->imageIndex -= 3;
  858.                 }
  859.         }
  860.        
  861.         //Setup Mask
  862.         Mask mask;
  863.         {
  864.                 mask.circle = mask.unused = 0;
  865.                 mask.w = 36;
  866.                 mask.h = 36;
  867.                 mask.x = h->x - mask.w / 2;
  868.                 mask.y = h->y - mask.h / 2;
  869.         }
  870.        
  871.         //Movement
  872.         {
  873.                 double grav = 0.2;
  874.                
  875.                 h->x += h->hsp;
  876.                 mask.x = h->x - mask.w / 2;
  877.                
  878.                 if (checkTileCollision(1, mask) == 1) {
  879.                         h->inwall = 1;
  880.                 }
  881.                
  882.                 h->y += h->vsp;
  883.                 h->vsp += grav;
  884.                 mask.y = h->y - mask.h / 2;
  885.                
  886.                 if (h->inwall == 0 && h->bounce == 0) {
  887.                         if (checkTileCollision(1, mask) == 1) {
  888.                                 h->bounce = 1;
  889.                                 h->vsp = -2;
  890.                         }
  891.                 }
  892.         }
  893.        
  894.         //Outside of room
  895.         {
  896.                 if ( (h->y > 500 && h->vsp >= 0) ||
  897.                          (h->x < -20 && h->hsp <= 0) ||
  898.                          (h->x > 660 && h->hsp >= 0) )
  899.                 {
  900.                         dead = 1;
  901.                 }
  902.         }
  903.        
  904.         //Collide with hero
  905.         {
  906.                 //Collide with shield
  907.                 if (checkCollision(mask, shieldMask) == 1) {
  908.                         createEffect(1, h->x - 20, h->y - 20);
  909.                         PHL_PlaySound(sounds[sndHit07], CHN_EFFECTS);
  910.                         dead = 1;
  911.                 }
  912.                 else if (checkCollision(mask, getHeroMask()) == 1) {
  913.                         if (heroHit(25, h->x) == 1) {
  914.                                 heroPoison();
  915.                         }
  916.                 }
  917.         }
  918.        
  919.         //Destroy object
  920.         {
  921.                 if (dead == 1) {
  922.                         enemyDestroy(h->id);
  923.                 }
  924.         }
  925.        
  926. }
  927.  
  928. void hydragoopDraw(Hydragoop* h)
  929. {
  930.         int cropX = 320;
  931.        
  932.         cropX += (int)h->imageIndex * 40;
  933.        
  934.         PHL_DrawSurfacePart(h->x - 20, h->y - 20, cropX, 480, 40, 40, images[imgMisc20]);
  935. }
  936.  
  937. //#rock
  938. void createHydrarock()
  939. {
  940.         int i;
  941.         for (i = 0; i < MAX_ENEMIES; i++) {
  942.                 if (enemies[i] == NULL) {
  943.                         Enemy* e = malloc(sizeof *e);
  944.                         Hydrarock* h = malloc(sizeof *h);
  945.                         h->id = i;
  946.                        
  947.                         h->x = 70 + (rand() % 26) * 20;
  948.                         h->y = -24;
  949.                        
  950.                         h->vsp = 0;
  951.  
  952.                         h->bounce = 0;
  953.                        
  954.                         h->imageIndex = 0;
  955.                        
  956.                         e->data = h;
  957.                         e->enemyStep = hydrarockStep;
  958.                         e->enemyDraw = hydrarockDraw;
  959.                         e->type = -1;
  960.                        
  961.                         enemies[i] = e;                
  962.                         i = MAX_ENEMIES;
  963.                 }
  964.         }
  965. }
  966.  
  967. void hydrarockStep(Hydrarock* h)
  968. {
  969.         //Animate
  970.         {
  971.                 h->imageIndex += 0.25;
  972.                 if (h->imageIndex >= 8) {
  973.                         h->imageIndex -= 8;
  974.                 }
  975.         }
  976.        
  977.         //Movement
  978.         {
  979.                 double grav = 0.15;
  980.                
  981.                 h->y += h->vsp;
  982.                 h->vsp += grav;
  983.         }
  984.        
  985.         //Setup Mask
  986.         Mask mask;
  987.         {
  988.                 mask.circle = mask.unused = 0;
  989.                 mask.w = 44;
  990.                 mask.h = 44;
  991.                 mask.x = h->x - mask.w / 2;
  992.                 mask.y = h->y - mask.h / 2;
  993.         }
  994.        
  995.         if (h->bounce == 0) {
  996.                 if (checkTileCollision(1, mask) == 1) {
  997.                         h->bounce = 1;
  998.                         h->vsp = -2;
  999.                         PHL_PlaySound(sounds[sndHit06], CHN_ENEMIES);
  1000.                 }
  1001.         }
  1002.        
  1003.         //Hero collision
  1004.         {
  1005.                 if (checkCollision(mask, getHeroMask()) == 1) {
  1006.                         heroHit(30, h->x);
  1007.                 }
  1008.         }
  1009.        
  1010.         //Weapon Collision
  1011.         {
  1012.                 int wid = checkWeaponCollision(mask);
  1013.                 if (wid != -1) {
  1014.                         weaponHit(weapons[wid]);
  1015.                         PHL_PlaySound(sounds[sndHit03], CHN_WEAPONS);
  1016.                 }
  1017.         }
  1018.        
  1019.         if (h->y >= 520) {
  1020.                 enemyDestroy(h->id);
  1021.         }
  1022. }
  1023.  
  1024. void hydrarockDraw(Hydrarock* h)
  1025. {
  1026.         int cropX = 128;
  1027.        
  1028.         cropX += (int)h->imageIndex * 64;
  1029.        
  1030.         PHL_DrawSurfacePart(h->x - 32, h->y - 32, cropX, 128, 64, 64, images[imgMisc32]);
  1031. }
  1032.  
  1033. //#electricity
  1034. void createHydrashock(int x, int y)
  1035. {
  1036.         int i;
  1037.         for (i = 0; i < MAX_ENEMIES; i++) {
  1038.                 if (enemies[i] == NULL) {
  1039.                         Enemy* e = malloc(sizeof *e);
  1040.                         Hydrashock* h = malloc(sizeof *h);
  1041.                         h->id = i;
  1042.                        
  1043.                         h->timer = 0;
  1044.                        
  1045.                         h->x = x;
  1046.                         h->y = y;
  1047.                        
  1048.                         h->angle = 0;
  1049.                        
  1050.                         h->imageIndex = 0;
  1051.                        
  1052.                         e->data = h;
  1053.                         e->enemyStep = hydrashockStep;
  1054.                         e->enemyDraw = hydrashockDraw;
  1055.                         e->type = -1;
  1056.                        
  1057.                         enemies[i] = e;                
  1058.                         i = MAX_ENEMIES;
  1059.                        
  1060.                         PHL_PlaySound(sounds[sndShot03], CHN_ENEMIES);
  1061.                 }
  1062.         }
  1063. }
  1064.  
  1065. void hydrashockStep(Hydrashock* h)
  1066. {
  1067.         //Animate
  1068.         {
  1069.                 h->imageIndex += 0.5;
  1070.                 if (h->imageIndex >= 4) {
  1071.                         h->imageIndex -= 4;
  1072.                 }
  1073.         }
  1074.        
  1075.         h->timer += 1;
  1076.        
  1077.         if (h->timer >= 20) {
  1078.                 if (h->timer == 20) {                  
  1079.                         //Set angle
  1080.                         h->angle = (atan2(h->x - (herox), heroy + 20 - h->y) * 180 / PI) + 90;
  1081.                 }
  1082.                
  1083.                 h->timer = 22;
  1084.                
  1085.                 //Movement
  1086.                 {
  1087.                         int spd = 5;
  1088.                         h->x += lengthdir_x(h->angle, spd);
  1089.                         h->y += lengthdir_y(h->angle, spd);
  1090.                 }
  1091.         }
  1092.        
  1093.         //Setup mask
  1094.         Mask mask;
  1095.         {
  1096.                 mask.unused = mask.circle = 0;
  1097.                 mask.w = 28;
  1098.                 mask.h = 28;
  1099.                 mask.x = h->x - mask.w / 2;
  1100.                 mask.y = h->y - mask.h / 2;
  1101.         }
  1102.        
  1103.         //Hero Collision
  1104.         {
  1105.                 if (checkCollision(mask, getHeroMask()) == 1) {
  1106.                         if (heroHit(25, h->x) == 1) {
  1107.                                 heroStun();
  1108.                         }
  1109.                 }
  1110.         }
  1111.        
  1112.         //Destroy if outside of room
  1113.         {
  1114.                 if (mask.x > 660 || mask.x + mask.w < -20 || mask.y > 500 || mask.y + mask.h < -20) {
  1115.                         enemyDestroy(h->id);
  1116.                 }
  1117.         }
  1118. }
  1119.  
  1120. void hydrashockDraw(Hydrashock* h)
  1121. {
  1122.         if (h->timer % 2 == 0) {
  1123.                 int cropX = (int)h->imageIndex * 64;
  1124.                
  1125.                 PHL_DrawSurfacePart(h->x - 32, h->y - 32, cropX, 192, 64, 64, images[imgMisc32]);
  1126.         }
  1127. }