Custom Movement

Been working on this for the past day. Why? Just because! Thought I’d share it. It’s not done yet, however. Mainly this is for anyone who wants the default system that they can customize. Wall detection works with any speed :slight_smile:

Just about everything was done using data from Graal, so should be pretty accurate. Not to mention I’m focusing on fixing problems that happened with the addition of ganis(cliff jumping, shallow water vs. swimming priorities, yadayada).

Features:

  • Wall Detection
  • Cliff Jumping
  • Modes: Idle,Walk,Push,Grab,Pull,Sit,Sleep,Swim,Jump
  • PUSH, GRAB, PULL each have their respective triggeractions fired
  • Custom speeds for just about everything
  • Weapon Support
  • Custom Sword(no damage yet), with custom bush cutting. Therefor, you can add anything you want to be cut down!

To Do:

  • Lifting/Carry
  • Hurting
  • Anything you can recommend!
  • Dynamic cliff jumping(variable heights)?
  • Moving into diagonal walls instead of sliding on them

I actually suggest downloading the level, however, as it has corresponding weapons and such needed.

There are probably a ton of things I could do more efficiently, but meh to that!

Oh right, reminds me I haven’t added “beds” yet.

Beware, adjusting playerx, playery, or freezeplayer, will force the “temporary invulnerability” to turn off. Swimming should also automatically turn it off. lol

I know I should do what I say, but my system is currently too fat (13kb) :[

Ya, I’ve encountered many problems when it comes to having to rescript the hurt system. It sucks. Hard.

What I’d really like to get done is some sort of dynamic cliff jumping, but I’ve always fallen short on that.

___Merged doublepost__________________

Well I’ve added hurting… sadly it isn’t interchangeable with the default system(sword.gani,hurt.gani) because no matter what, Graal is always going to check for attacks whether your movement is disabled or not -_- (since Graal’s method is checking if OTHER players on the screen’s gani == sword.gani == hit). And hurt.gani automatically makes Graal do flickering and crap.

So I had to go an alternative route and use different ganis for sword and hurt, which… well that sucks.

[QUOTE=Shiny;14273]So I had to go an alternative route and use different ganis for sword and hurt, which… well that sucks.[/QUOTE]

Yeah I was thinking of doing that. In my case its just a matter of removing the replaceani.
Note to self, edit the “damage system” so I can have “-Movement” then “-Projectile”.

Currently loads as “-Projectile” then “-Movement”. This causes a 0.05 sec delay when throwing your own object, however its a pay off so people don’t get a 0.05 second hurt delay, which in turn, would screw some things up by moving/freezing the player which forces the hurt knock back and animation to cease.

I’ll admit I’m cheating a bit at the moment, using native sword detection and hurting.
The whole thing would run much smoother if I could run it all under one NPC. Could cut the code down a LOT if I could use parameters in functions or if I could do dynamic variable names like “hello#v(num) = pi”, or better yet, multi-dimensional arrays wtf[1,3].
That would save on a lot of friggin’ code D:

But that, with the 13kb character limit for online script sizes (limit being blessed upon us by the client itself.), offers some sort of challenge. Like making a game on the f**king Atari.

Heh… I’ve always gotten too annoyed with custom systems to ever finish them. Usually when I come along to anything more complicated than basic movement/grab/pull/push crap.

Though I realize in GS1, custom is a lot more limited than the default is. For example, now I have to find a way to rescript all the player and NPC communications like registering an NPC being hit by a player and such in a manner that is easily accessed(if (washit), for example)… is it REALLY worth it? I guess that’d matter if this had a real reason, but it doesn’t :stuck_out_tongue:

Right now the system is at 10kb.

Fixed the washit issue by taking the hit detection, reversing it, and placing it in the sword weapon to callnpc washit… way easier than I expected!

One problem I’m having is when the player’s x/y’s floating value becomes really obscure(from getting hit, for example), sliding becomes buggy. Any help with a solution?

[QUOTE=Shiny;14301]One problem I’m having is when the player’s x/y’s floating value becomes really obscure(from getting hit, for example), sliding becomes buggy. Any help with a solution?[/QUOTE]

int() the player’s position when he hits a wall, this will allow him to “snap” to the closest possible position to the wall as well as fix all those problems with floating values :open_mouth:

Or in the script you can just have something like:

playerx = int(playerx*100)/100;

and that would not allow the floating value to be more than two decimal places long.

[QUOTE=Downsider;14302]
int() the player’s position when he hits a wall, this will allow him to “snap” to the closest possible position to the wall as well as fix all those problems with floating values :open_mouth:

Or in the script you can just have something like:

playerx = int(playerx*100)/100;

and that would not allow the floating value to be more than two decimal places long.
[/QUOTE]

I’m going to try the second method… I already do the first. The problem is, if I hit a wall going right, it snaps to the wall, but it doesn’t fix the Y, which is important since I will be sliding around the edge via the Y-coordinate.

edit: okay, that didn’t work. I need to make the floating point always divisible by 0.0625(1/16, one pixel). :confused:

[QUOTE=Shiny;14303]
I’m going to try the second method… I already do the first. The problem is, if I hit a wall going right, it snaps to the wall, but it doesn’t fix the Y, which is important since I will be sliding around the edge via the Y-coordinate.

edit: okay, that didn’t work. I need to make the floating point always divisible by 0.0625(1/16, one pixel). :confused:
[/QUOTE]

Easy.

playerx = int(playerx*16)/16;

EDIT: I do that in my Mega Man movement system too :D!

Actually I ended up with this, heh:
playerx = int(playerx/.0625).0625;
playery = int(playery/.0625)
.0625;

And with this new-found knowledge, I was able to increase the sliding time(which I’ve been wanting to do), so thanks doubly!

Ooo, great minds think alike :open_mouth:

Current build:

Features:

  • Wall Detection
  • Cliff Jumping
  • Modes: Idle,Walk,Push,Grab,Pull,Sit,Sleep,Swim,Jump
  • PUSH, GRAB, PULL each have their respective triggeractions fired
  • Custom speeds for just about everything
  • Weapon Support
  • Custom Sword(no damage yet), with custom bush cutting. Therefor, you can add anything you want to be cut down!
  • Hit-detection and hurt detection all completed, integrated with NPC’s and washit checks
  • Explosions DO hurt now
  • Improved wall sliding, speed depends on player speed to a degree

To Do:

  • Lifting/Carry
  • Dynamic cliff jumping(variable heights)?
  • Moving into diagonal walls instead of sliding on them

Funny tidbit: Stefan once began improving the default system, such as wall detection(just like with mines, so you can’t slide through cracks) and players BITCHED and moaned about it, because their levels were built stupidly and needed that exploit in order to function correctly. And instead of fixing their tile errors, ended up making Stefan undo the fixes and stagnating improvement -_-

[QUOTE=Shiny;14307]

Funny tidbit: Stefan once began improving the default system, such as wall detection(just like with mines, so you can’t slide through cracks) and players BITCHED and moaned about it, because their levels were built stupidly and needed that exploit in order to function correctly. And instead of fixing their tile errors, ended up making Stefan undo the fixes and stagnating improvement -_-
[/QUOTE]

Well, hey, you know what they say:

If it isn’t broken, it isn’t Graal.

Yes I recall that, v3.
Had improved collision detection. A lot of “Events” depended on the abuse of tiles to snap through corners.

Here’s some problems I’ve found.

You can push/pull over water.
Attacking is a bit bugged. I can hit the female NPC from far away.
You don’t lose HP from bombs and stuff (you probably knew that)

EDIT:
You can hit the female NPC if she’s in the correct x coordinate but the y coordinate doesn’t seem to matter.

[QUOTE=Spooon;14321]
You can push/pull over water.[/quote]
Ya, the detection for walls/water with pushing and pulling would be in the blocks themselves, not the movement so that’s something I’ve been ignoring.

[QUOTE=Spooon;14321]
You don’t lose HP from bombs and stuff (you probably knew that)[/quote]
Ya, I don’t like dying when I test stuff :frowning:

[QUOTE=Spooon;14321]

You can hit the female NPC if she’s in the correct x coordinate but the y coordinate doesn’t seem to matter.
[/QUOTE]

Ya I actually noticed that yesterday… I just fixed that, apparent typo(py-py instead of py-oy).

Thanks for all the debugging :slight_smile:

Also, I want to implement arrow detection but arrows are so broken it’s almost impossible :confused:

[QUOTE=Shiny;14326]

Also, I want to implement arrow detection but arrows are so broken it’s almost impossible :confused:
[/QUOTE]

for (i=0;i<arrowscount;i++) {
  if (arrows[i].x in |playerx,playerx+2| && arrows[i].y in |playery,playery+3|) {
    if (vecx(arrows[i].dir) == -vecx(playerdir) || vecy(arrows[i].dir) == -vecy(playerdir)) {
      setplayerprop #c, I blocked your arrow, fool!; 
      removearrow i;
      break;
    }
    removearrow i;
    setplayerprop #c, Ouchie arrows :(;
    break;
  }
}

Off the top of my head, should work methinks? You can definitely rewrite it better, lol.

[QUOTE=Downsider;14329]

for (i=0;i<arrowscount;i++) {
  if (arrows[i].x in |playerx,playerx+2| && arrows[i].y in |playery,playery+3|) {
    if (vecx(arrows[i].dir) == -vecx(playerdir) || vecy(arrows[i].dir) == -vecy(playerdir)) {
      setplayerprop #c, I blocked your arrow, fool!; 
      removearrow i;
      break;
    }
    removearrow i;
    setplayerprop #c, Ouchie arrows :(;
    break;
  }
}

Off the top of my head, should work methinks? You can definitely rewrite it better, lol.
[/QUOTE]

It’s the buggyness of arrows in offline mode that’s the problem. Mainly being reflected no matter which direction you’re going or where they hit from.

When the arrow gets within range, the client takes over before any and all scripts. ie: take the arrow, or get hit by the arrow.

Arrow system rewrite:

Systems NPC:

//NPC made by Downsider
if (playerenters) {
  toweapons Arrow System;
  setarray this.arrowx,50;
  setarray this.arrowy,50;
  setarray this.arrowdir,50;
  setarray this.arrowismine,50;
  timeout = 0.05;
}

if (actionprojectile) {
  if (strequals(#p(2),newarrow)) {
    for (i=0;i<50;i++) {
      if (this.arrowx[i] <= 0) {
        this.arrowx[i] = strtofloat(#p(3));
        this.arrowy[i] = strtofloat(#p(4));
        this.arrowdir[i] = strtofloat(#p(5));
        if (strequals(#a,#p(6))) {
          this.arrowismine[i] = 1;
        } else {
          this.arrowismine[i] = 0;
        }
        break;
      }
    }
  }
  if (strequals(#p(2),removearrow)) {
    this.arrowx[strtofloat(#p(3))] = -10;
  }
}

if (timeout) {
  timeout = 0.05;
  if (!isweapon) {
    return;
  }
  prepare();
  moveArrows();
  drawArrows();
  checkHurt();
  reflectArrows();
}

function prepare() {
  if (!strequals(#s(this.olevel),#L)) {
    setarray this.arrowx,50;
    setarray this.arrowy,50;
    setarray this.arrowdir,50;
    setarray this.arrowismine,50;
    for (i=0;i<50;i++) {
      this.arrowx[i] = 0;
      this.arrowy[i] = 0;
      this.arrowdir[i] = 0;
      this.arrowismine[i] = 0;
    }
  }
  setstring this.olevel,#L;
}

function removeArrow() {
  setshootparams removearrow,#v(this.target);
  shoot -10,-10,0.05,0.05,0.05,0.05,0.05,0.05,0.05,;
}

function shootArrow() {
  setshootparams newarrow,#v(this.sx),#v(this.sy),#v(this.sd),#a;
  shoot -10,-10,0.05,0.05,0.05,0.05,0.05,0.05,0.05,;
}

function reflectArrows() {
  for (i=0;i<50;i++) {
    if (this.arrowx[i] > 0) {
      if (this.arrowx[i] in |playerx,playerx+2| && this.arrowy[i] in |playery+1,playery+3|) {
        if (vecx(this.arrowdir[i]) + vecx(playerdir) == 0 && vecy(this.arrowdir[i]) + vecy(playerdir) == 0 && strequals(#m,idle)) {
          if (this.arrowismine[i] == 0) {
            this.target = i;
            removeArrow();
            this.sx = playerx+1+vecx(playerdir);
            this.sy = playery+1.5+vecy(playerdir);
            this.sd = playerdir;
            shootArrow();
            putleaps 4,this.sx,this.sy;
            return;
          }
        }
      }
    }
  }
}

function checkHurt() {
  for (i=0;i<50;i++) {
    if (this.arrowx[i] > 0) {
      if (this.arrowx[i] in |playerx,playerx+2| && this.arrowy[i] in |playery+1,playery+3|) {
        if (vecx(this.arrowdir[i]) + vecx(playerdir) == 0 && vecy(this.arrowdir[i]) + vecy(playerdir) == 0 && strequals(#m,idle)) {
        } else {
          if (this.arrowismine[i] == 0) {
            this.target = i;
            removeArrow();
            hurt 1;
            return;
          }
        }
      }
    }
  }
}

function drawArrows() {
  for (i=0;i<50;i++) {
    hideimg 300+i;
    if (this.arrowx[i] > 0) {
      showimg 300+i,sprites.png,this.arrowx[i],this.arrowy[i];
      changeimgvis 300+i,1;
      if (this.arrowdir[i] == 0) {
        changeimgpart 300+i,11,422,9,30;
      }
      if (this.arrowdir[i] == 1) {
        changeimgpart 300+i,0,412,30,9;
      }
      if (this.arrowdir[i] == 2) {
        changeimgpart 300+i,1,426,9,30;
      }
      if (this.arrowdir[i] == 3) {
        changeimgpart 300+i,0,402,30,9;
      }
    }
  }
}

function moveArrows() {
  for (i=0;i<50;i++) {
    if (this.arrowx[i] > 0) {
      this.arrowx[i] += vecx(this.arrowdir[i]);
      this.arrowy[i] += vecy(this.arrowdir[i]);
      if (this.arrowx[i] < 0 || this.arrowx[i] > 64) {
          this.arrowx[i] = -1;
          this.arrowy[i] = -1;
      }
      if (this.arrowy[i] < 0 || this.arrowy[i] > 64) {
        this.arrowx[i] = -1;
        this.arrowy[i] = -1;
      }
    }
  }
}

How to shoot an arrow via script:

//NPC made by Downsider
if (playertouchsme) {
  toweapons New Bow;
}

if (weaponfired) {
  setani shoot,;
  freezeplayer 0.5;
  this.sx = playerx+1+vecx(playerdir);
  this.sy = playery+1.5+vecy(playerdir);
  this.sd = playerdir;
  shootArrow();
}

function shootArrow() {
  setshootparams newarrow,#v(this.sx),#v(this.sy),#v(this.sd),#a;
  shoot -10,-10,0.05,0.05,0.05,0.05,0.05,0.05,0.05,;
}

Haven’t tested it online because Beholder hasn’t been responding to me :’(

Should work, though. Arrows reflect in this script :smiley: