Pocket Dimensional Clash 2

Complete Pocket Dimensional Clash 2 2.3

No permission to download
Project is completed.
Actually Noid is not a character I particularly like. But I will give it a try because I like your projects.
Thank you!
Noid was a huge challenge. Jhfer used sprites from the original NES game and even some sprites from the obscure fan game "Yo Noid 2 - Enter the Noid."

But the character needed more movement, and even though I don't consider myself a spriter, I drew a lot of animations for him—basically all the yo-yo attacks were done by me :)
 
@Psykai I am trying to undestand what happened at Rugal fight (22:00)
But about the lack of music on select screen (at 15:00), its a random engine bug, because all the select screen uses the same music and you can see on the video I posted above that there is no issue with the music on te select screen after Willy's fight.
 
@Psykai
Jhfer helped me figure out what caused the bug:
In PDC3, there's an entity that's called during hyper, indicating to the player that they can move the Noid.
pdc - 0246.png

However, since I LOAD this entity in the models and not in the Noid header, I never received a warning in the log that this entity doesn't exist. And since the spawnbind() function doesn't have a safe check—to determine if the entity I'm referring to exists—for some reason, the engine decided to pick the first nearby entity (in this case, Rugal) and bind it.

C-like:
void spawnbind(void Name, float dx, float dy, float dz, int iDir,int iBind)
{ // Spawn and bind other entity
   void self = getlocalvar("self");
   void Spawn;

    Spawn = spawn01(Name, dx, dy, 0);
    bindentity(Spawn, self, dx, dz, dy, iDir, iBind);
}
Unless you try to get some value from the entity, if you spawn via script an entity that doesn't exist (IOW, its not on the models.txt), the engine simply ignores it, without causing a warning in the log.
This also happens in the Paragumugen video.

now the function has a safe check and I should make an update soon

C-like:
void spawnbind(void Name, float dx, float dy, float dz, int iDir,int iBind)
{ // Spawn and bind other entity
   void self = getlocalvar("self");
   void Spawn;

    Spawn = spawn01(Name, dx, dy, 0);
    if (Spawn){// safe check
    bindentity(Spawn, self, dx, dz, dy, iDir, iBind);
    }
}
 
J
@Psykai
Jhfer helped me figure out what caused the bug:
In PDC3, there's an entity that's called during hyper, indicating to the player that they can move the Noid.
View attachment 11035

However, since I LOAD this entity in the models and not in the Noid header, I never received a warning in the log that this entity doesn't exist. And since the spawnbind() function doesn't have a safe check—to determine if the entity I'm referring to exists—for some reason, the engine decided to pick the first nearby entity (in this case, Rugal) and bind it.

C-like:
void spawnbind(void Name, float dx, float dy, float dz, int iDir,int iBind)
{ // Spawn and bind other entity
   void self = getlocalvar("self");
   void Spawn;

    Spawn = spawn01(Name, dx, dy, 0);
    bindentity(Spawn, self, dx, dz, dy, iDir, iBind);
}
Unless you try to get some value from the entity, if you spawn via script an entity that doesn't exist (IOW, its not on the models.txt), the engine simply ignores it, without causing a warning in the log.
This also happens in the Paragumugen video.

now the function has a safe check and I should make an update soon

C-like:
void spawnbind(void Name, float dx, float dy, float dz, int iDir,int iBind)
{ // Spawn and bind other entity
   void self = getlocalvar("self");
   void Spawn;

    Spawn = spawn01(Name, dx, dy, 0);
    if (Spawn){// safe check
    bindentity(Spawn, self, dx, dz, dy, iDir, iBind);
    }
}

Just FYI, not only here, but in every script, and that means outside OpenBOR too, it's always advisable to include guards when one process depends on another's success. This will save you SO many headaches and nearly impossible to trace bugs down the road.

In this case, I would just write it to intentionally "crash" the game, since it's a mission critical functionality and you always want to catch the error.

C-like:
void spawnbind(void Name, float dx, float dy, float dz, int iDir,int iBind){ // Spawn and bind other entity

   void self = getlocalvar("self");
   void Spawn;
    
   Spawn = spawn01(Name, dx, dy, 0);   

    if (Spawn){// safe check
        shutdown(1, "\n\n Error - Spawnbind(" + Name + ", " + dx + ", " + dy + ", " + dz + ", " + iDor + ", " + iBind + "): Spawn failed.");
        return;
    } 

    bindentity(Spawn, self, dx, dz, dy, iDir, iBind);

}
 
In this case, I would just write it to intentionally "crash" the game, since it's a mission critical functionality and you always want to catch the error.
ah I wasn't aware of the "shutdown" function, thanks for the tip!
All my script do have it, but I forgot to add it to spawnbind.

What I think its funny is the engine randomly picking a different entity for that.
 
ah I wasn't aware of the "shutdown" function, thanks for the tip!
All my script do have it, but I forgot to add it to spawnbind.

What I think its funny is the engine randomly picking a different entity for that.

It's not random at all. The engine's spawn system caches the last used spawn data - this has a ton of advantages, but it can mess with your head when scripting if you're not aware of it

That's why before you set up any spawn parameters, you generally use clearspawnentity() to make sure all the spawn data is clean. In your case, what's happening is the engine compared the model name you supplied to its indexed list so it could place model index into spawn cache - but there was no match. Therefore the cache didn't get updated. So whatever model index already happened to be in the spawn cache is what you get when the spawn function fires.

DC
 
That's why before you set up any spawn parameters, you generally use clearspawnentity() to make sure all the spawn data is clean.
Another thing I wasn't aware of :)
But there is a clearspawnentity(), inside of the spawn01 function - which has the safety check too:

C-like:
void spawn01(void vName, float fX, float fY, float fZ)
{
    //spawn01 (Generic spawner)
    //Damon Vaughn Caskey
    //07/06/2007
    //
    //Spawns entity next to caller.
    //
    //vName: Model name of entity to be spawned in.
    //fX: X location adjustment.
    //fZ: Y location adjustment.
      //fY: Z location adjustment.
    void self = getlocalvar("self"); //Get calling entity.
    void vSpawn; //Spawn object.
    int  iDirection = getentityproperty(self, "direction");

    clearspawnentry(); //Clear current spawn entry.
      setspawnentry("name", vName); //Acquire spawn entity by name.

    if (iDirection == 0){ //Is entity facing left?                 
          fX = -fX; //Reverse X direction to match facing.
    }

      fX = fX + getentityproperty(self, "x"); //Get X location and add adjustment.
      fY = fY + getentityproperty(self, "a"); //Get Y location and add adjustment.
      fZ = fZ + getentityproperty(self, "z"); //Get Z location and add adjustment.
    
    vSpawn = spawn(); //Spawn in entity.

  if (vSpawn){// safe check

    changeentityproperty(vSpawn, "position", fX, fZ, fY); //Set spawn location.
    changeentityproperty(vSpawn, "direction", iDirection); //Set direction.
    changeentityproperty(vSpawn, "parent", self); //Set parent.
    
    return vSpawn; //Return spawn.
    
  }
}

But I will add it to this function too, thanks!
 
Another thing I wasn't aware of :)
But there is a clearspawnentity(), inside of the spawn01 function - which has the safety check too:

C-like:
void spawn01(void vName, float fX, float fY, float fZ)
{
    //spawn01 (Generic spawner)
    //Damon Vaughn Caskey
    //07/06/2007
    //
    //Spawns entity next to caller.
    //
    //vName: Model name of entity to be spawned in.
    //fX: X location adjustment.
    //fZ: Y location adjustment.
      //fY: Z location adjustment.
    void self = getlocalvar("self"); //Get calling entity.
    void vSpawn; //Spawn object.
    int  iDirection = getentityproperty(self, "direction");

    clearspawnentry(); //Clear current spawn entry.
      setspawnentry("name", vName); //Acquire spawn entity by name.

    if (iDirection == 0){ //Is entity facing left?                
          fX = -fX; //Reverse X direction to match facing.
    }

      fX = fX + getentityproperty(self, "x"); //Get X location and add adjustment.
      fY = fY + getentityproperty(self, "a"); //Get Y location and add adjustment.
      fZ = fZ + getentityproperty(self, "z"); //Get Z location and add adjustment.
   
    vSpawn = spawn(); //Spawn in entity.

  if (vSpawn){// safe check

    changeentityproperty(vSpawn, "position", fX, fZ, fY); //Set spawn location.
    changeentityproperty(vSpawn, "direction", iDirection); //Set direction.
    changeentityproperty(vSpawn, "parent", self); //Set parent.
   
    return vSpawn; //Return spawn.
   
  }
}

But I will add it to this function too, thanks!

I would most definitely do a shutdown immediately if spawning fails. You can just about guarantee it's going to break something downstream and then be much harder to diagnose, so might as well do a controlled error right at point of failure. That way you know right where and what the problem is and can fix it instead of dealing with a "WTF?!" moment later on.

On the spawning random stuff even when you clear, that could potentially still happen on a name mismatch because then you'd get index 0 and whatever model that happens to be.

DC
 
if (Spawn){// safe check shutdown(1, "\n\n Error - Spawnbind(" + Name + ", " + dx + ", " + dy + ", " + dz + ", " + iDor + ", " + iBind + "): Spawn failed."); return; }
Shouldn't this part be like this? This should trigger only if "Spawn" is empty

C-like:
if (!Spawn){// safe check
        shutdown(1, "\n\n Error - Spawnbind(" + Name + ", " + dx + ", " + dy + ", " + dz + ", " + iDor + ", " + iBind + "): Spawn failed.");
        return;
    }

Also why you use return on this case?
 
Shouldn't this part be like this? This should trigger only if "Spawn" is empty

C-like:
if (!Spawn){// safe check
        shutdown(1, "\n\n Error - Spawnbind(" + Name + ", " + dx + ", " + dy + ", " + dz + ", " + iDor + ", " + iBind + "): Spawn failed.");
        return;
    }

Also why you use return on this case?

Yes, it should be if(!spawn). I just forgot the ! in front of spawn. Derp.

Return is technically redundant sine the shutdown should stop everything anyway, but it's 100% benign and I alike to be extra safe.

DC
 
I did a NOID playthrough. I had a funny glitch that got The Hulk stuck on my head when I used the NOID's Super attack { A, down, Down super }
 
O Ilusionista updated Pocket Dimensional Clash 2 with a new update entry:

Bug fix - Version 2.3

- Fixed a bug during Noid hyper move
- New playable character: Noid, from the game Yo Noid! (NES), enabled from the start in this version, but will need to be unlocked in the next version.
- Improved respawn system, especially in the Castle stage in the Golden Axe universe. The platforming stage in the same universe can still be problematic in co-op, so it will either be modified or removed in the next version.
- Improved the Spider Queen boss, which now ignores the hole in the level, making...

Read the rest of this update entry...
 
I finally tested the new version. the Noid character, even if I'm not familliar with him (it does not exist in my country) was pretty fun to play.
I really like the diversity of characters again.

BTW I had some bug with Blink in training mode (using the "old" version)
The bug was in right area of training stage, close to wall forward throw from grab one of the raining dummy.
It got me quit the training stage.
But no actual crash of the game. just went back to game menu.

EDIT : I managed to do it again. same crash. kind of "lower" area of the right wall of stage. Certainly works in other places with walls...
 
BTW I had some bug with Blink in training mode (using the "old" version)
The bug was in right area of training stage, close to wall forward throw from grab one of the raining dummy.
It got me quit the training stage.
But no actual crash of the game. just went back to game menu.
I advice you to use the newer version, is the one where the gamepads works.
I am aware of that, what happens is: when Blink release the target, it is released inside the wall. And since the wall is too tall and there is no antiwall code on the slam finish, the entity gets removed and the stage ends.
 
Back
Top Bottom