Frost Bow

So, I acquired a copy of the Graal 1.41 client I think maybe two years ago. Strictly offline, but it’s still pretty cool. Comes with all the levels and just about all of the weapons from Graal Classic in that era. Has the level editor, but it’s built into the client rather than coming as a separate executable. Poking around through all of the .graal files, came across ragnarok’s ice castle levels. Within was the Ice Bow. I thought “Oh, sweet man, never got to see this in action before.” I endowed myself with magic to make it usable. It fired off a shot and I thought “Whoa, nice. Custom arrow and everything”. Only thing was, it didn’t work against baddies/NPCs. I looked at the script…or rather scripts (it uses putnpc for each arrow shot direction…and each one of those uses putnpc to call the iceblock.txt script when it makes a hit). It’s only hit detection was playertouchsme conditions…so it seems this weapon was usable against other players only. I’m actually making my own offline adventure and thought an Ice Bow would be a cool weapon to feature. So, I redesigned it to only have to call the iceblock.txt script file via putnpc. Tried using showimg, but that won’t actually freeze the NPC. It is…chunky..but hey, works against baddies and custom NPCs now :). I’ll write a reply here to include the original script(s) made by Ragnarok.
Frost Bow In-Game Weapon Script

////Frost Bow Created by Kevin
if (playertouchsme) {
  toweapons Frost Bow;
  hidelocal;
}

if (weaponfired&&playerdarts>5&&magicendowed&&magicendowed&&playermp>10&&playerdir=0) {
  playermp -= 10;
  freezeplayer 0.6;
  setbow wicebow1.gif;
  playersprite = 33;
  playerdarts -= 5;
  sleep .5;
  set iceboltactive;
  while (iceboltactive) {
    showimg 0, wicearru.gif, x, y-1;
    sleep 0.05;
    y -= 1.25;
    // BADDIE HIT CHECK
    for (i=0; i<compuscount; i++) {
      if (abs(compus[i].x - x) < 1 && abs(compus[i].y - (y-1)) < 1) {
        // spawn the iceblock image
        putnpc wiceblock.gif,iceblock.txt,compus[i].x,compus[i].y;
        unset iceboltactive;
        hideimg 0;
        hitcompu i,2,0,0;
        break;
      }
    }
    //NPC HIT CHECK
    for (i=0; i<npcscount; i++) {
      if (abs(npcs[i].x - x) < 1 &&abs(npcs[i].y - (y-1)) < 1) {
        // spawn the iceblock image
        putnpc wiceblock.gif,iceblock.txt, npcs[i].x, npcs[i].y;
        unset iceboltactive;
        hideimg 0;
        npcs[i].hearts -= 2;
        break;
      }
    }
    if (!iceboltactive) break;
    if (y < 2) {
      unset iceboltactive; hideimg 0;
    }
  }
}

// ----------------------------------------------------
// FIRE LEFT
// ----------------------------------------------------
if (weaponfired&&playerdarts>5&&magicendowed&&magicendowed&&playermp>10&&playerdir == 1) {
  playermp -= 10;
  freezeplayer 0.6;
  setbow wicebow1.gif;
  playersprite = 33;
  playerdarts -= 5;
  sleep .5;
  set iceboltactive;
  while (iceboltactive) {
    showimg 0, wicearrl.gif, x-1, y;
    sleep 0.05;
    x -= 1.25;
    // BADDIE HIT CHECK
    for (i=0; i<compuscount; i++) {
      if (abs(compus[i].x - (x-1)) < 1 &&abs(compus[i].y - y) < 1) {
        putnpc wiceblock.gif,iceblock.txt, compus[i].x, compus[i].y;
        unset iceboltactive;
        hideimg 0;
        hitcompu i,2,0,0;
        
        break;
      }
    }
    // NPC HIT CHECK
    for (i=0; i<npcscount; i++) {
      if (abs(npcs[i].x - x) < 1 &&
        abs(npcs[i].y - (y-1)) < 1) {
        // spawn the iceblock image
        putnpc wiceblock.gif,iceblock.txt, npcs[i].x, npcs[i].y;
        unset iceboltactive;
        hideimg 0;
        npcs[i].hearts -= 2;
        
        break;
      }
    }
    if (!iceboltactive) break;
    if (x < 2) { unset iceboltactive; hideimg 0; }
  }
}

// ----------------------------------------------------
// FIRE DOWN
// ----------------------------------------------------
if (weaponfired&&playerdarts>5&&magicendowed&&magicendowed&&playermp>10&&playerdir == 2) {
  playermp -= 10;
  freezeplayer 0.6;
  setbow wicebow1.gif;
  playersprite = 33;
  playerdarts -= 5;
  sleep .5;
  set iceboltactive;
  while (iceboltactive) {
    showimg 0, wicearrd.gif, x, y+1;
    sleep 0.05;
    y += 1.25;
    // BADDIE HIT CHECK
    for (i=0; i<compuscount; i++) {
      if (abs(compus[i].x - x) < 1 &&
        abs(compus[i].y - (y+1)) < 1) {
        putnpc wiceblock.gif,iceblock.txt, compus[i].x, compus[i].y;
        unset iceboltactive;
        hideimg 0;
        hitcompu i,2,,;
        
        break;
      }
    }
    //NPC HIT CHECK
    for (i=0; i<npcscount; i++) {
      if (abs(npcs[i].x - x) < 1 &&
        abs(npcs[i].y - (y-1)) < 1) {
        // spawn the iceblock image
        putnpc wiceblock.gif,iceblock.txt, npcs[i].x, npcs[i].y;
        unset iceboltactive;
        hideimg 0;
        npcs[i].hearts -= 2;
        
        break;
      }
    }
    if (!iceboltactive) break;
    if (y > 62) { unset iceboltactive; hideimg 0; }
  }
}

// ----------------------------------------------------
// FIRE RIGHT
// ----------------------------------------------------
if (weaponfired&&playerdarts>5&&magicendowed&&magicendowed&&playermp>10&&playerdir == 3) {
  playermp -= 10;
  freezeplayer 0.6;
  setbow wicebow1.gif;
  playersprite = 33;
  playerdarts -= 5;
  sleep .5;
  set iceboltactive;
  while (iceboltactive) {
    showimg 0, wicearrr.gif, x+1, y;
    sleep 0.05;
    x += 1.25;

    // BADDIE HIT CHECK
    for (i=0; i<compuscount; i++) {
      if (abs(compus[i].x - (x+1)) < 1 &&
        abs(compus[i].y - y) < 1) {
        putnpc wiceblock.gif,iceblock.txt, compus[i].x, compus[i].y;
        unset iceboltactive;
        hideimg 0;
        hitcompu i,2,,;
        
        break;
      }
    }
    //NPC HIT CHECK
    for (i=0; i<npcscount; i++) {
      if (abs(npcs[i].x - x) < 1 &&
        abs(npcs[i].y - (y-1)) < 1) {
        // spawn the iceblock image
        putnpc wiceblock.gif,iceblock.txt, npcs[i].x, npcs[i].y;
        unset iceboltactive;
        hideimg 0;
        npcs[i].hearts -= 2;
        
        break;
      }
    }
    if (!iceboltactive) break;
    if (x > 62) { unset iceboltactive; hideimg 0; }
  }
}

iceblock.txt script file

if (created) {
sleep 3;
destroy;
}

wicearrd
wicearrr
wiceblock
wicebow
wicebow1

The reason for the four separate weaponfired conditionals is because if it’s all wrapped in one, the arrow will change direction if the player moves after they shoot it. So, if you fire upward, arrow will go upward,..but as soon as you walk left, right, or down, it will change to that direction. So you would have to stay still until it hits a baddy or NPC, or disappears past the border coordinates.

Ice Bow by Ragnarok - In-Game Bow

//Ice Bow Created by Ragnarok
if (playertouchsme) {
  toweapons Ice Bow;
  set goticebow;
  hidelocal;
}
if (weaponfired && playerdarts>0&&playermp>5&&magicendowed) {
  freezeplayer 0.6;
  setbow wicebow1.gif;
  playersprite = 33;
  playermp-=5;
  playerdarts--;
  sleep.5;
  if (playerdir==0) {
    putnpc wicearrd.gif,icearrd.txt,x,y-1;
  }
  if (playerdir==1) {
    putnpc wicearrl.gif,icearrl.txt,x-1,y;
  }
  if (playerdir==2) {
    putnpc wicearrd.gif,icearrd.txt,x,y+1;
  }
  if (playerdir==3) {
    putnpc wicearrr.gif,icearrr.txt,x+1,y;
  }
}

Ice Arrow Down txt Script File

if (playerenters) timeout = 0.05;
if (playertouchsme) {
  if (playerdir==0) putleaps 5,x,y-1;
  else {
    set icefreeze;
    putnpc wiceblock.gif,iceblock.txt,playerx-2/16,playery-7/16;
  }
  destroy;
}
if (timeout) {
  timeout = 0.05;
  y+=0.7;
  if (y>61) destroy;
}

Ice arrow right txt script file

if (playerenters) timeout = 0.05;
if (playertouchsme) {
  if (playerdir==1) putleaps 5,x-1,y-1;
  else {
    set icefreeze;
    putnpc wiceblock.gif,iceblock.txt,playerx-2/16,playery-7/16;
  }
  destroy;
}
if (timeout) {
  timeout = 0.05;
  x+=0.7;
  if (x>61) destroy;
}

Ice arrow up script txt file

if (playerenters) timeout = 0.05;
if (playertouchsme) {
  if (playerdir==2) putleaps 5,x,y;
  else {
    set icefreeze;
    putnpc wiceblock.gif,iceblock.txt,playerx-2/16,playery-7/16;
  }
  destroy;
}
if (timeout) {
  timeout = 0.05;
  y-=0.7;
  if (y<2) destroy;
}

Ice arrow right script txt file

if (playerenters) timeout = 0.05;
if (playertouchsme) {
  if (playerdir==3) putleaps 5,x+1,y-1;
  else {
    set icefreeze;
    putnpc wiceblock.gif,iceblock.txt,playerx-2/16,playery-7/16;
  }
  destroy;
}
if (timeout) {
  timeout = 0.05;
  x-=0.7;
  if (x<2) destroy;
}

Iceblock script txt file

if (playerenters) {
  if (icefreeze) {
    freezeplayer 3;
    x = playerx-2/16;
    y = playery-7/16;
    unset icefreeze;
  }
  timeout = 3;
}
if (timeout) {
  putleaps 5,x+1,y;
  putleaps 5,x+1,y+2;
  destroy;
}