Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "weapon.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include "hero.h"
  6. #include "PHL.h"
  7. #include "game.h"
  8. #include "object.h"
  9.  
  10. void updateWeaponMask(Weapon* w);
  11.  
  12. void addWeapon(int type, int x, int y)
  13. {
  14.         if (heroAmmo > 0 || type == SWORD) {
  15.                 int i, weaponcount = 0;
  16.                
  17.                 //Count
  18.                 for (i = 0; i < MAX_WEAPONS; i++) {
  19.                         if (weapons[i] != NULL) {
  20.                                 if (weapons[i]->type != SWORD) {
  21.                                         weaponcount += 1;
  22.                                 }
  23.                         }
  24.                 }
  25.                
  26.                 if (type == BOMB) { //Bombs have one lower limit
  27.                         weaponcount += 1;
  28.                 }
  29.                
  30.                 if (type == SWORD || weaponcount < (2 + hasItem[15])) { //3 projectiles if have green scroll
  31.                
  32.                         if (type != SWORD) {
  33.                                 PHL_PlaySound(sounds[sndShot01], CHN_WEAPONS);
  34.                         }
  35.                
  36.                         for (i = 0; i < MAX_WEAPONS; i++) {
  37.                                 if (weapons[i] == NULL) {                      
  38.                                         Weapon* w = malloc(sizeof *w);
  39.                                         w->id = i;
  40.                                         w->type = type;
  41.  
  42.                                         w->x = x;
  43.                                         w->y = y;
  44.  
  45.                                         w->hsp = 0;
  46.                                         w->vsp = 0;
  47.                                        
  48.                                         w->grav = 0;                                   
  49.                                         w->imageIndex = 0;
  50.                                        
  51.                                         w->power = 1;
  52.                                         w->timer = 0;
  53.                                         w->state = 0;
  54.                                         w->cooldown = 0;
  55.                                         w->hitflag = 0;
  56.                                        
  57.                                         w->dir = getHeroDirection();
  58.                                        
  59.                                         w->weaponMask.circle = 0;
  60.                                         w->weaponMask.unused = 0;
  61.                                         w->weaponMask.x = 0;
  62.                                         w->weaponMask.y = 0;
  63.                                         w->weaponMask.w = 10;
  64.                                         w->weaponMask.h = 10;
  65.                                        
  66.                                         if (w->type == SWORD)
  67.                                         {
  68.                                                 w->weaponMask.unused = 1;                                              
  69.                                         }else if (w->type == ARROW)
  70.                                         {
  71.                                                 w->hsp = 8 * getHeroDirection();
  72.                                                 w->weaponMask.y += 16;
  73.                                                 w->weaponMask.w = 32;
  74.                                                 w->weaponMask.h = 6;
  75.                                         }else if (w->type == AXE)
  76.                                         {
  77.                                                 w->hsp = 2 * getHeroDirection();
  78.                                                 w->vsp = -6;
  79.                                                 w->grav = 0.2;
  80.                                                 w->weaponMask.w = w->weaponMask.h = 24;
  81.                                                 w->y += (40 - getHeroMask().h) - ((40 - w->weaponMask.h) / 2);
  82.                                                 w->weaponMask.x = w->x + ((40 - w->weaponMask.w) / 2);
  83.                                                 w->weaponMask.y = w->y + ((40 - w->weaponMask.h) / 2);
  84.                                                
  85.                                         }else if (w->type == BOOMERANG)
  86.                                         {
  87.                                                 w->x += 20;
  88.                                                 w->y += 20;
  89.                                                 updateWeaponMask(w);
  90.                                                 w->weaponMask.circle = 1;
  91.                                                 w->weaponMask.w = 16;
  92.                                                
  93.                                                 w->hsp = 6 * getHeroDirection();
  94.                                                 w->vsp = getHeroDirection(); //Vsp is used for starting direction
  95.                                                 w->timer = 120;
  96.                                         }else if (w->type == FIREBALL)
  97.                                         {
  98.                                                 w->vsp = -2;
  99.                                                 w->grav = 0.1;
  100.                                                
  101.                                                 w->hsp = 2 * getHeroDirection();
  102.                                                
  103.                                                 w->x += 20;
  104.                                                 w->y += 20;
  105.                                                
  106.                                                 w->weaponMask.circle = 1;
  107.                                                 w->weaponMask.w = 15;
  108.                                                 updateWeaponMask(w);
  109.                                                
  110.                                                 Mask tempMask;
  111.                                                 tempMask.circle = tempMask.unused = 0;
  112.                                                 tempMask.y = w->y - w->weaponMask.w;
  113.                                                 tempMask.x = w->x - w->weaponMask.w;
  114.                                                 tempMask.w = tempMask.h = w->weaponMask.w * 2;                                         
  115.                                                
  116.                                                 PHL_Rect collide = getTileCollision(1, tempMask);
  117.                                                 if (collide.x == -1) {
  118.                                                         collide = getTileCollision(3, tempMask);
  119.                                                 }
  120.                                                 if (collide.x != -1) {
  121.                                                         w->y = collide.y + 40 + w->weaponMask.w;
  122.                                                 }
  123.                                                
  124.                                         }else if (w->type == BOMB)
  125.                                         {
  126.                                                 w->dir = 0;
  127.                                                 w->vsp = -2;
  128.                                                 w->grav = 0.1;
  129.                                                 w->hsp = getHeroDirection();
  130.                                                
  131.                                                 w->weaponMask.unused = 1;
  132.                                                
  133.                                                 Mask tempMask;         
  134.                                                 tempMask.y = w->y + 8;
  135.                                                 tempMask.x = w->x + 8;
  136.                                                 tempMask.w = tempMask.h = 24;
  137.                                                 tempMask.circle = tempMask.unused = 0;
  138.                                                
  139.                                                 PHL_Rect collide = getTileCollision(1, tempMask);
  140.                                                 if (collide.x == -1) {
  141.                                                         collide = getTileCollision(3, tempMask);
  142.                                                 }
  143.                                                 if (collide.x != -1) {
  144.                                                         w->y = collide.y + 40 - 8;
  145.                                                 }
  146.                                         }
  147.                                        
  148.                                         updateWeaponMask(w);
  149.                                        
  150.                                         weapons[i] = w;
  151.                                         i = MAX_WEAPONS;
  152.                                        
  153.                                         if (type != SWORD) {
  154.                                                 heroAmmo -= 1;
  155.                                         }
  156.                                 }
  157.                         }
  158.                 }
  159.         }
  160. }
  161.  
  162. //When a weapon lands a hit
  163. void weaponHit(Weapon* w)
  164. {      
  165.         //w->cooldown = 15;
  166.         w->hitflag = 1;
  167.        
  168.         if (w->type == SWORD) {
  169.                 createEffect(1, w->weaponMask.x + (w->weaponMask.w / 2) - 10 + (rand() % 20) - 10, w->weaponMask.y + (w->weaponMask.h / 2) - 10 + (rand() % 20) - 10);
  170.                 PHL_PlaySound(sounds[sndHit02], CHN_WEAPONS);
  171.         }else if (w->type == ARROW || w->type == AXE) {
  172.                 PHL_PlaySound(sounds[sndPi02], CHN_WEAPONS);
  173.                 createEffect(1, w->x, w->y);
  174.                 weaponDestroy(w->id);
  175.         }else if (w->type == BOOMERANG) {
  176.                 PHL_PlaySound(sounds[sndPi02], CHN_WEAPONS);
  177.                 createEffect(1, w->x, w->y - 40 + (rand() % 40) + 1);
  178.         }else if (w->type == FIREBALL) {
  179.                 PHL_PlaySound(sounds[sndPi02], CHN_WEAPONS);
  180.                 createEffect(1, w->x - 20, w->y - 20);
  181.                 //weaponDestroy(w->id);
  182.         }else if (w->type == BOMB) {
  183.                
  184.         }
  185. }
  186.  
  187. void weaponStep(Weapon* w)
  188. {
  189.         char dead = 0;
  190.        
  191.         if (w->cooldown > 0) {
  192.                 w->cooldown -= 1;
  193.         }
  194.        
  195.         if (w->hitflag == 1) {
  196.                 w->hitflag = 0;
  197.                 w->cooldown = 15;
  198.         }
  199.        
  200.         if (w->type == SWORD)
  201.         {
  202.                 double imgind = getHeroImageIndex();
  203.                 if ((getHeroState() != 1 && getHeroState() != 5) || imgind >= 4) { //Not slashing
  204.                         dead = 1;
  205.                 }
  206.                
  207.                 w->x = herox;
  208.                 w->y = heroy;
  209.                 updateWeaponMask(w);
  210.                        
  211.         }else if (w->type == ARROW)
  212.         {
  213.                 //Yes, this does have to be done before movement
  214.                 //Destroy if out of view or collides with wall
  215.                 if (w->x > 640 || w->x + 40 < 0 || checkTileCollision(1, w->weaponMask) == 1) {
  216.                         weaponHit(w);
  217.                 }
  218.                
  219.                 w->x += w->hsp;
  220.                 updateWeaponMask(w);
  221.         }else if (w->type == AXE)
  222.         {
  223.                 w->y += w->vsp;
  224.                 w->vsp += w->grav;
  225.                 updateWeaponMask(w);
  226.                
  227.                 PHL_Rect collide = getTileCollisionWeapon(1, w->weaponMask);
  228.                 if (collide.x == -1) {
  229.                         collide = getTileCollision(3, w->weaponMask);
  230.                 }
  231.                
  232.                 if (collide.x != -1) {
  233.                         if (w->vsp <= 0) {
  234.                                 w->y = collide.y + 40 - ((40 - w->weaponMask.h) / 2);
  235.                                 w->vsp = 0;
  236.                         }else{
  237.                                 weaponHit(w);
  238.                                 return;
  239.                         }
  240.                 }
  241.                
  242.                 w->x += w->hsp;
  243.                 updateWeaponMask(w);
  244.                
  245.                 collide = getTileCollisionWeapon(1, w->weaponMask);
  246.                
  247.                 if (collide.x != -1) {
  248.                         if (w->hsp > 0) {
  249.                                 w->x = collide.x - 40 + ((40 - w->weaponMask.w) / 2);
  250.                         }else{
  251.                                 w->x = collide.x + 40 - ((40 - w->weaponMask.w) / 2);
  252.                         }
  253.                 }                      
  254.                
  255.                 //Animate
  256.                 {
  257.                         w->imageIndex += 0.33;
  258.                         if (w->imageIndex >= 8) {
  259.                                 w->imageIndex -= 8;
  260.                         }
  261.                 }
  262.                
  263.                 if (w->x > 640 || w->x + 40 < 0 || w->y > 520) {
  264.                         dead = 1;
  265.                 }
  266.         }else if (w->type == BOOMERANG)
  267.         {
  268.                 w->x += w->hsp;
  269.                 w->hsp -= 0.125 * (w->vsp); //Vsp is recycled to be the starting direction
  270.                 if (w->hsp >= 6) {
  271.                         w->hsp = 6;
  272.                 }
  273.                 if (w->hsp <= -6) {
  274.                         w->hsp = -6;
  275.                 }
  276.                
  277.                 w->dir = 1;
  278.                 if (w->hsp < 0) {
  279.                         w->dir = -1;
  280.                 }
  281.                
  282.                 w->y = heroy + 20;
  283.                 updateWeaponMask(w);
  284.                
  285.                 w->imageIndex -= (0.33 * w->vsp);
  286.                 if (w->imageIndex < 0) {
  287.                         w->imageIndex += 8;
  288.                 }
  289.                 if (w->imageIndex >= 8) {
  290.                         w->imageIndex -= 8;
  291.                 }
  292.                
  293.                 w->timer -= 1;
  294.                 if (w->timer <= 0) {
  295.                         createEffect(5, w->x, w->y);
  296.                         dead = 1;
  297.                 }
  298.         }else if (w->type == FIREBALL)
  299.         {              
  300.                 //Move vertically
  301.                 w->y += w->vsp;
  302.                 w->vsp += w->grav;
  303.  
  304.                 Mask tempMask;
  305.                 tempMask.circle = tempMask.unused = 0;
  306.                 tempMask.y = w->y - w->weaponMask.w;
  307.                 tempMask.w = tempMask.h = w->weaponMask.w * 2;
  308.                 tempMask.x = w->x - w->weaponMask.w;
  309.                
  310.                 //Check vertical collision
  311.                 PHL_Rect collide = getTileCollisionWeapon(1, tempMask);
  312.                 if (collide.x == -1) {
  313.                         collide = getTileCollisionWeapon(3, tempMask);
  314.                 }
  315.                
  316.                 if (collide.x != -1) {
  317.                         if (w->vsp <= 0) {
  318.                                 w->y = collide.y + 40 + w->weaponMask.w;
  319.                                 w->vsp = 0;
  320.                         }else{
  321.                                 w->y = collide.y - w->weaponMask.w;
  322.                                 if (w->timer == 0) {
  323.                                         w->vsp = -2;
  324.                                         PHL_PlaySound(sounds[sndPi02], 2);
  325.                                 }else if (w->timer == 1) {
  326.                                         w->vsp = -1;
  327.                                         PHL_PlaySound(sounds[sndPi02], 2);
  328.                                 }else{
  329.                                         weaponHit(w);
  330.                                         dead = 1;
  331.                                 }
  332.                                 w->timer += 1;                 
  333.                         }
  334.                        
  335.                         tempMask.y = w->y - w->weaponMask.w;
  336.                 }
  337.                
  338.                 //Move horizontally
  339.                 w->x += w->hsp;
  340.                 tempMask.x = w->x - w->weaponMask.w;
  341.                
  342.                 //Check horizontal collision
  343.                 collide = getTileCollisionWeapon(1, tempMask);
  344.                 if (collide.x != -1) {
  345.                         if (w->hsp > 0) {
  346.                                 w->x = collide.x - (tempMask.w / 2) ;
  347.                         }else{
  348.                                 w->x = collide.x + 40 + (tempMask.w / 2);
  349.                         }
  350.                         w->hsp *= -1;
  351.                         tempMask.x = w->x - w->weaponMask.w;
  352.                
  353.                         w->dir = 1;
  354.                         if (w->hsp < 0) {
  355.                                 w->dir = -1;
  356.                         }
  357.                 }
  358.                
  359.                 updateWeaponMask(w);
  360.                
  361.                 //animate
  362.                 {
  363.                         w->imageIndex += 0.5;
  364.                         if (w->imageIndex >= 8) {
  365.                                 w->imageIndex -= 8;
  366.                         }
  367.                 }
  368.                
  369.                 if (w->x > 640 || w->x + 40 < 0 || w->y > 520) {
  370.                         dead = 1;
  371.                 }
  372.         }else if (w->type == BOMB)
  373.         {
  374.                 if (w->state == 0) { //Bouncing bomb
  375.                         Mask tempMask;         
  376.                         tempMask.y = w->y  + 8;
  377.                         tempMask.w = tempMask.h = 24;
  378.                         tempMask.circle = tempMask.unused = 0;
  379.                        
  380.                         w->x += w->hsp;
  381.                         tempMask.x = w->x + 8;
  382.                         PHL_Rect collide = getTileCollision(1, tempMask);
  383.                         if (collide.x != -1) {
  384.                                 if (w->hsp > 0) {
  385.                                         w->x = collide.x - 40 + 8;
  386.                                 }else{
  387.                                         w->x = collide.x + 40 - 8;
  388.                                 }
  389.                                 w->hsp *= -1;
  390.                                 tempMask.x = w->x + 8;
  391.                         }
  392.                        
  393.                         w->imageIndex -= (0.33 * w->hsp);
  394.                         if (w->imageIndex < 0) {
  395.                                 w->imageIndex += 8;
  396.                         }
  397.                         if (w->imageIndex >= 8) {
  398.                                 w->imageIndex -= 8;
  399.                         }
  400.                        
  401.                         w->y += w->vsp;
  402.                         w->vsp += w->grav;
  403.                        
  404.                         tempMask.y = w->y + 8;
  405.                         collide = getTileCollision(1, tempMask);
  406.                         if (collide.x == -1) {
  407.                                 collide = getTileCollision(3, tempMask);
  408.                         }
  409.                         if (collide.x != -1) {
  410.                                 if (w->vsp <= 0) {
  411.                                         w->y = collide.y + 40 - 8;
  412.                                         w->vsp = 0;
  413.                                 }else{
  414.                                         w->y = collide.y - 40 + 8;
  415.                                         if (w->timer == 0) {
  416.                                                 w->vsp = -2;
  417.                                                 PHL_PlaySound(sounds[sndPi02], CHN_WEAPONS);
  418.                                         }else if (w->timer == 1) {
  419.                                                 w->vsp = -1;
  420.                                                 PHL_PlaySound(sounds[sndPi02], CHN_WEAPONS);
  421.                                         }else{
  422.                                                 w->state = 1;
  423.                                                 w->imageIndex = 0;
  424.                                                 w->weaponMask.unused = 0;
  425.                                                 PHL_PlaySound(sounds[sndBom03], CHN_WEAPONS);
  426.                                         }
  427.                                         w->timer += 1;
  428.                                 }
  429.                         }
  430.                        
  431.                         updateWeaponMask(w);
  432.                                
  433.                         if (w->x > 640 || w->x + 40 < 0 || w->y > 520) {
  434.                                 //weaponDestroy(w->id);
  435.                                 dead = 1;
  436.                         }
  437.                 }
  438.                 else if (w->state == 1) { //Explosion
  439.                         updateWeaponMask(w);
  440.                        
  441.                         if (checkCollision(getHeroMask(), w->weaponMask) == 1) {
  442.                                 heroHit(20, w->x + 20);
  443.                         }
  444.                        
  445.                         w->imageIndex += 0.34;
  446.                         if (w->imageIndex >= 11) {
  447.                                 //weaponDestroy(w->id);
  448.                                 dead = 1;
  449.                         }
  450.                 }
  451.         }
  452.        
  453.         if (dead == 1) {
  454.                 weaponDestroy(w->id);
  455.         }
  456. }
  457.  
  458. void weaponDraw(Weapon* w)
  459. {
  460.         if (w->type == SWORD) {        
  461.                 //PHL_DrawMask(w->weaponMask);
  462.                
  463.                 //Draw Sword
  464.                 double imgind = getHeroImageIndex();
  465.                 int dir = getHeroDirection();
  466.                 if (imgind < 4) {
  467.                         int swordx = 0, swordy = 0;
  468.                         int scropx = 40 * (int)floor(imgind),
  469.                                 scropy = 240;
  470.                         if (imgind < 1) {
  471.                                 swordy = -16;
  472.                                 swordx = -8;
  473.                         }else if (imgind < 2) {
  474.                                 swordy = -8;
  475.                                 swordx = 24;
  476.                         }else if (imgind < 4) {
  477.                                 swordy = 14;
  478.                                 swordx = 26;
  479.                         }
  480.                        
  481.                         if (dir == -1) {
  482.                                 swordx *= -1;
  483.                                 scropx += 160;
  484.                         }
  485.                        
  486.                         if (getHeroInvincible() % 2 == 0) {
  487.                                 PHL_DrawSurfacePart(herox - 20 + swordx, heroy + swordy, scropx, scropy, 40, 40, images[imgHero]);
  488.                         }
  489.                        
  490.                         //PHL_DrawSurfacePart(w->x, w->y, 0, 240, 40, 40, images[imgHero]);
  491.                 }
  492.                
  493.         }
  494.         else if (w->type == ARROW)
  495.         {
  496.                 int dx = 240;
  497.                 if (w->hsp <= 0) {
  498.                         dx += 40;
  499.                 }
  500.                 PHL_DrawSurfacePart(w->x, w->y, dx, 200, 40, 40, images[imgMisc20]);
  501.         }else if (w->type == AXE)
  502.         {
  503.                 int dx = 0;
  504.                 if (w->hsp <= 0) {
  505.                         dx = 320;
  506.                 }
  507.                 PHL_DrawSurfacePart(w->x, w->y, dx + ((int)w->imageIndex * 40), 240, 40, 40, images[imgMisc20]);
  508.         }else if (w->type == BOOMERANG)
  509.         {
  510.                 PHL_DrawSurfacePart(w->x - 20, w->y - 20, 320 + ((int)w->imageIndex * 40), 160, 40, 40, images[imgMisc20]);
  511.         }else if (w->type == FIREBALL)
  512.         {
  513.                 int dx = 0;
  514.                 if (w->hsp <= 0) {
  515.                         dx = 320;
  516.                 }
  517.                 PHL_DrawSurfacePart(w->x - 20, w->y - 20, dx + ((int)w->imageIndex * 40), 280, 40, 40, images[imgMisc20]);
  518.         }else if (w->type == BOMB)
  519.         {
  520.                 if (w->state == 0) {
  521.                         PHL_DrawSurfacePart(w->x, w->y, (int)w->imageIndex * 40, 160, 40, 40, images[imgMisc20]);
  522.                 }
  523.                 else if (w->state == 1) {
  524.                         //PHL_DrawMask(w->weaponMask);
  525.                        
  526.                         int cx = (int)w->imageIndex * 128;
  527.                         int cy = 0;
  528.                         while (cx >= 640) {
  529.                                 cx -= 640;
  530.                                 cy += 96;
  531.                         }
  532.                         PHL_DrawSurfacePart(w->weaponMask.x, w->weaponMask.y, cx, cy, 128, 96, images[imgExplosion]);
  533.                 }
  534.         }
  535.         //PHL_DrawMask(w->weaponMask);
  536. }
  537.  
  538. void updateWeaponMask(Weapon* w)
  539. {
  540.         if (w->type == SWORD) {
  541.                 //Sword mask
  542.                 //swordMask.unused = 0;
  543.                 double imgind = getHeroImageIndex();
  544.                 int dir = getHeroDirection();
  545.                 w->weaponMask.unused = 0;
  546.                
  547.                 if (imgind < 1) {
  548.                         /*w->weaponMask.w = 8;
  549.                         w->weaponMask.h = 24;
  550.                         w->weaponMask.x = herox - 4 + (dir * -8); //herox - 20 + (direction * -8) + 16
  551.                         w->weaponMask.y = heroy - 8; //heroy - 16 + 8
  552.                         */
  553.                         w->weaponMask.unused = 1;
  554.                 }else if (imgind < 2) {
  555.                         w->weaponMask.w = 32;
  556.                         w->weaponMask.h = 38;
  557.                         w->weaponMask.x = herox - 20 + (dir * 28) + 4;
  558.                         w->weaponMask.y = heroy - 6;
  559.                 }else if (imgind < 3) {
  560.                         w->weaponMask.w = 24;
  561.                         w->weaponMask.h = 20;
  562.                         w->weaponMask.x = herox - 20 + (dir * 26) + 8;
  563.                         w->weaponMask.y = heroy + 18;
  564.                 }else if (imgind < 4) {
  565.                         w->weaponMask.w = 24;
  566.                         w->weaponMask.h = 6;
  567.                         w->weaponMask.x = herox - 20 + (dir * 26) + 8;
  568.                         w->weaponMask.y = heroy + 30;
  569.                 }
  570.         }else if (w->type == ARROW) {
  571.                 w->weaponMask.x = w->x;
  572.                 w->weaponMask.y = w->y + 16;
  573.                 if (w->hsp > 0) {
  574.                         w->weaponMask.x += 8;
  575.                 }
  576.                
  577.         }else if (w->type == AXE) {
  578.                 w->weaponMask.x = w->x + ((40 - w->weaponMask.w) / 2);
  579.                 w->weaponMask.y = w->y + ((40 - w->weaponMask.h) / 2);
  580.         }else if (w->type == BOOMERANG) {
  581.                 w->weaponMask.x = w->x;
  582.                 w->weaponMask.y = w->y;
  583.         }else if (w->type == FIREBALL) {
  584.                 w->weaponMask.x = w->x;
  585.                 w->weaponMask.y = w->y;
  586.         }else if (w->type == BOMB) {
  587.                 if (w->state == 1) { //Update mask on explosion
  588.                         w->weaponMask.x = w->x - 44;
  589.                         w->weaponMask.y = w->y - 44 - 8;
  590.                         w->weaponMask.w = 128;
  591.                         w->weaponMask.h = 90; //Hits blocks below
  592.                 }
  593.         }
  594. }
  595.  
  596. void weaponDestroy(int id)
  597. {      
  598.         if (weapons[id] != NULL) {
  599.                 free(weapons[id]);
  600.         }
  601.         weapons[id] = NULL;
  602. }
  603.