Solved Create a confusion spell that reverses the directional keys

Question that is answered or resolved.

kimono

Well-known member
Hello Openbor friends.

I would like to create the following spell within a projectile:
The player is affected for 3 seconds by the inversion of the directional keys (left becomes right, down becomes jump and vice versa).

Here is the projectile launched by Hyoh, hyohshot.txt:
Code:
name        hyohshot
health        10
type        none
candamage     player obstacle
projectilehit 0
remove         0
shadow        0

didhitscript       data/scripts/confusion.c

##ANIMATIONS#############################################################################

anim idle
    delay    15
    offset    24 88
    bbox 6 59 36 29
    drawmethod alpha 6
    drawmethod channel 0.7  
    attack1 6 59 36 29 2 1 0 0 0 0
    frame    data/chars/weapons/hyohshot1.png
    frame    data/chars/weapons/hyohshot2.png
    frame    data/chars/weapons/hyohshot3.png
    frame    data/chars/weapons/hyohshot4.png
    frame    data/chars/weapons/hyohshot5.png
    frame    data/chars/weapons/hyohshot6.png
    frame    data/chars/weapons/hyohshot7.png
    frame    data/chars/weapons/hyohshot8.png


The header of the player character Kenshiro:
Code:
##MAIN
name                Kenshiro
type                player
candamage            player enemy npc obstacle

##LIFE
health                100

##POWER
offense             1 #SCRIPT

##SPEED
speed                10 #SCRIPT
running             20 4 1.5 1 0

##JUMP
jumpmove     3 3
jumpheight     4

##ENERGY
mp                    120
mprate              1 #SCRIPT

##GRAB
grabdistance         33 #36/33/30
grabfinish             0 #PLAYER=0/ENEMY=1

##WEIGHT/HEIGHT
antigravity            -6 #-3/-6/-9
nohithead              1

##MISC
jugglepoints        30
guardpoints            20
guardrate            4
risetime            170
riseinv                0.4 1 #HEROES 0.4 - ENEMY 0 - BOSS 0.4
makeinv                2 0
atchain                1 2
combostyle             2
gfxshadow            1 2
dust                dust
bflash                block
holdblock            2
death                1

##ICONS
icon                data/chars/kenshiro/icon.png 1
iconpain            data/chars/kenshiro/iconpain.png 1

##DIESOUND
diesound            sound    data/chars/kenshiro/voice/die.wav

##Weapons
weapons                  kenshirosuper kenshiropawn kenshiro
load                kenshirosuper
load                kenshiropawn

animationscript         data/scripts/player.c
ondoattackscript       data/scripts/projectile_return.c
onmoveascript         data/scripts/shadowbase.c
onspawnscript         data/scripts/onspawn.c
ondrawscript        data/scripts/shadowon.c
updateentityscript data/scripts/confusion.c

The confusion spell in question:
Code:
void main()
{
    // 'self' exists when called as updateentityscript
    void self   = getlocalvar("self");
    // 'target' exists when called as didhitscript (projectile hit)
    void target = getlocalvar("target");

    float now = openborvariant("elapsed_time");

    // ------------------------------------------------------
    // CASE 1 : called by projectile (we have a target)
    // ------------------------------------------------------
    if(target)
    {
        // We only want to confuse players
        if(getentityproperty(target, "type") == openborconstant("TYPE_PLAYER"))
        {
            // We use entityvar index 0 as "confused flag"
            // and entityvar index 1 as "confuse end time"
            if(getentityvar(target, 0) != 1)
            {
                setentityvar(target, 0, 1);              // mark as confused
                setentityvar(target, 1, now + 3000);     // store end time (3 seconds)
            }
        }
        return; // projectile path done
    }

    // ------------------------------------------------------
    // CASE 2 : called every frame on the player
    // ------------------------------------------------------
    if(!self) return;

    // Only run logic on players
    if(getentityproperty(self, "type") != openborconstant("TYPE_PLAYER"))
        return;

    // Read confusion state
    // var 0 = flag (1 = confused)
    // var 1 = endtime (ms)
    int   confused  = getentityvar(self, 0);
    float endtime   = getentityvar(self, 1);

    if(confused != 1)
        return; // player is not confused, nothing to do

    // Check if confusion expired
    if(now >= endtime)
    {
        setentityvar(self, 0, 0); // clear flag
        setentityvar(self, 1, 0); // clear time
        return;
    }

    // ------------------------------------------------------
    // Confusion is active -> invert controls
    // ------------------------------------------------------

    // Get player index (needed for playerkeys)
    // Some builds always return -1, so we fallback to 0 (P1).
    int p = getentityproperty(self, "playerindex");
    if(p < 0)
        p = 0;

    // Read current inputs from that player slot
    int key_up    = playerkeys(p, 0, "moveup");
    int key_down  = playerkeys(p, 0, "movedown");
    int key_left  = playerkeys(p, 0, "moveleft");
    int key_right = playerkeys(p, 0, "moveright");

    // Get current position
    float x = getentityproperty(self, "x");
    float z = getentityproperty(self, "z");

    // Movement speed while confused (tweak if needed)
    float speed = 2.0;

    // Left becomes "move right"
    if(key_left)
    {
        changeentityproperty(self, "position", x + speed, z);
    }

    // Right becomes "move left"
    if(key_right)
    {
        changeentityproperty(self, "position", x - speed, z);
    }

    // Up becomes duck
    if(key_up)
    {
        // Player must have an animation called "duck"
        performattack(self, "duck");
    }

    // Down becomes jump
    if(key_down)
    {
        // Player must have an animation called "jump"
        performattack(self, "jump");
    }
}
Unfortunately, there is no inversion of the player Kenshiro's controls when he is hit by the projectile.
What do I need to change in this script so that the key reversal takes place on the player?
Thank you all :)
 
Last edited:
Solution
I have solved this question weeks ago but haven't found time to share the solution until now.
My solution is to give Kenshiro keyscript then override key input with opposite direction when confused spell is active or Kenshiro is confused.
Kenshiro's keyscript is confukey.c and here's the script:
C:
void main()
{
    void self = getlocalvar("self");
    int iPIndex = getentityproperty(self,"playerindex"); //Get player index
    void iLeftH = playerkeys(iPIndex, 0, "moveleft"); //   Held status of "Left"
    void iRightH = playerkeys(iPIndex, 0, "moveright"); // Held status of "Right"
    void iUpH = playerkeys(iPIndex, 0, "moveup"); //   Held status of "Up"
    void iDownH = playerkeys(iPIndex, 0, "movedown"); // Held status of "Down"...
I have solved this question weeks ago but haven't found time to share the solution until now.
My solution is to give Kenshiro keyscript then override key input with opposite direction when confused spell is active or Kenshiro is confused.
Kenshiro's keyscript is confukey.c and here's the script:
C:
void main()
{
    void self = getlocalvar("self");
    int iPIndex = getentityproperty(self,"playerindex"); //Get player index
    void iLeftH = playerkeys(iPIndex, 0, "moveleft"); //   Held status of "Left"
    void iRightH = playerkeys(iPIndex, 0, "moveright"); // Held status of "Right"
    void iUpH = playerkeys(iPIndex, 0, "moveup"); //   Held status of "Up"
    void iDownH = playerkeys(iPIndex, 0, "movedown"); // Held status of "Down"
    int State = getentityvar(self, "State");

    if(State=="Confuse"){
      if(iLeftH){
        changeplayerproperty(iPIndex, "keys", openborconstant("FLAG_MOVERIGHT"));
      } else if(iRightH){
        changeplayerproperty(iPIndex, "keys", openborconstant("FLAG_MOVELEFT"));
      }
      if(iUpH){
        changeplayerproperty(iPIndex, "keys", openborconstant("FLAG_MOVEDOWN"));
      } else if(iDownH){
        changeplayerproperty(iPIndex, "keys", openborconstant("FLAG_MOVEUP"));
      }
    }
}

The confused state is given by the projectile which is hyohshot. This shot uses this didhitscript:
Hyhit.c
C:
void main(){
    void self = getlocalvar("self");
    int Time = getentityproperty(self,"mp");
    void target = getlocalvar("damagetaker");
    void Spawn;

    if(target){
      setentityvar(target, "State", "Confuse");

      Spawn = spawnbind("Pusing", target, 0, 0, 0, 1, 0);
      changeentityproperty(Spawn, "parent", target);
      setentityvar(Spawn, "Statime", 2*Time);
    }
}

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
    //fY: Y location
    //fZ: Z location

    void self = getlocalvar("self"); //Get calling entity.
    void vSpawn; //Spawn object.

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

    vSpawn = spawn(); //Spawn in entity
    changeentityproperty(vSpawn, "position", fX, fZ, fY); //Set spawn location. 

    return vSpawn; //Return spawn
}

void spawnbind(void Name, void Target, float dx, float dy, float dz, int Dir, int Flag)
{ // Spawn entity and bind it
   void self = getlocalvar("self");
   void Spawn;

   Spawn = spawn01(Name, dx, dy, dz);
   bindentity(Spawn, Target, dx, dz, dy, Dir, Flag);

   return Spawn;
}

This script gives the confused state and also spawn other entity called Pusing. Pusing is the effect entity similar to ones used by Booster items i.e applies flashing color for certain time. However when its time has ended, it will end both the flashing and confused state.
I'll post Pusing entity tomorrow.
 
Solution
Thanks for reminding.

Anyways, here's Pusing.txt:
Code:
name        Pusing
type        none


anim    idle
@script
  if(frame>=1){
    void self = getlocalvar("self");
    void P = getentityproperty(self, "parent");
    int Len = getentityvar(self, "Statime");

    if(frame==1){
      changedrawmethod(P, "enabled", 1);
    }
    if(frame==8 || frame==10 || frame==12 || frame==14 || frame==16){
      changedrawmethod(P, "tintmode", 3);
      changedrawmethod(P, "tintcolor", rgbcolor(200,0,0));
    }
    if(frame==9 || frame==11 || frame==13 || frame==15){
      changedrawmethod(P, "tintmode", 0);
    }
    if(frame==17){
      if(Len > 0){
        setentityvar(self, "Statime", Len-1);
        updateframe(self, 8); //Change frame
      } else {
        setentityvar(self, "Statime", 0);
      }
    }
    if(frame==18){
      changedrawmethod(P, "enabled", 0);
      setentityvar(P, "State", NULL());
      setentityvar(P, "Statime", NULL());

      killentity(self); //Suicide!
    }
  }
@end_script
    delay    2
    offset    0 0
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    delay    5
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif # 10
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif # loops here
    frame    data/chars/misc/empty.gif
    frame    data/chars/misc/empty.gif # 20
 
This confusion script is a masterpiece.
Thanks for being one of those who take on such nice programming challenges ;)
Starting from this model, I added a poisoning script, creating damage over time and tinting the affected entity with each tick.
 
Back
Top Bottom