Jump to content

Photo

[Request] A simple script for the shields

Item Script Request

  • Please log in to reply
9 replies to this topic

#1 FireSeraphim

FireSeraphim

    Behold the might of legend!

  • Members
  • Real Name:Patrick Casey Spurlock

Posted 13 October 2017 - 02:00 AM

I would like to request a script that can be applied to the shield items that would
reduce the damage link takes from enemies as a flat damage reduction value as opposed to the division based method the
blue, red and gold rings use and I would like it to be able to be added to/stacked with the ring's defense value.
Ideally the script would only need one argument. (This is for Wanderer from Hyrule)

#2 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 13 October 2017 - 04:15 AM

I would like to request a script that can be applied to the shield items that would
reduce the damage link takes from enemies as a flat damage reduction value as opposed to the division based method the
blue, red and gold rings use and I would like it to be able to be added to/stacked with the ring's defense value.
Ideally the script would only need one argument. (This is for Wanderer from Hyrule)

 

I need a bit of clarification. Is this an effect that you want active from all directions, or only from a shielded direction?

 

Something along this line, might do the trick:

 

int Z_Arr[256];

const itn SHIELD_DAMAGE_REDUCTION = 0;

void SetShieldDamageReduction(int amt) { Z_Arr[SHIELD_DAMAGE_REDUCTION] = amt; }
int GetShieldDamageReduction() { return Z_Arr[SHIELD_DAMAGE_REDUCTION]; }

const int EW_MISC_Z_FLAGS = 8;
const int EW_DAMAGE_REDUCED = 000010000b;

const int EW_DAMAGE_REDUCTION_DIST = 12;

const int I_DR_SHIELD = 100; //item ID of shield

item script DamageReductionShield
{
    void run(int msg, int amt)
    {
        if ( msg ) Screen->Message(msg);
        SetShieldDamageReduction(Abs(amt));
    }
}

bool IsReverseDir(int dir1, int dir2){
    if ( dir1 == DIR_UP && dir2 == DIR_DOWN ) return true;
    if ( dir2 == DIR_UP && dir1 == DIR_DOWN ) return true;
    if ( dir1 == DIR_LEFT && dir2 == DIR_RIGHT ) return true;
    if ( dir2 == DIR_LEFT && dir1 == DIR_RIGHT ) return true;
    return false;
}


bool DR_Shield_DistXY(eweapon b, int distance) {
    int distx; int disty;
    if ( Link->X > b->X ) distx = Link->X - b->X;
    else distx = b->X - Link->X;
    
    if ( Link->Y > b->Y ) disty = Link->Y - b->Y;
    else disty = b->Y - Link->Y;

    return ( distx <= distance && disty <= distance );
}


void ShieldReduction(int amt)
{
    eweapon e; int numew = Screen->NumEWeapons();
    for ( ; numew > 0; numew-- )
    {
        e = Screen->LoadEWeapon(numew);
        if ( ( ew->Misc[EW_MISC_Z_FLAGS]&EW_DAMAGE_REDUCED == 0 ) )
        {
            if ( IsReverseDir(ew->Dir, Link->Dir) )
            {
                if ( DR_Shield_DistXY(ew, EW_DAMAGE_REDUCTION_DIST) )
                {
                    ew->Damage -= amt;
                    ew->Misc[EW_MISC_Z_FLAGS |= EW_DAMAGE_REDUCED;
                }
            }
        }
    }
}

void DoShieldDamageReduction()
{
    if ( Link->Item[I_DR_SHIELD] ) { ShieldReduction(GetShieldDamageReduction()); }
}

global script Shield_DR
{
    void run()
    {
        while(1)
        {
            DoShieldDamageReduction();
            Waitdraw();
            
            Waitframe();
        }
    }
}

Edited by ZoriaRPG, 13 October 2017 - 04:29 AM.


#3 FireSeraphim

FireSeraphim

    Behold the might of legend!

  • Members
  • Real Name:Patrick Casey Spurlock

Posted 13 October 2017 - 08:41 AM

Just in all direction in general.

#4 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 13 October 2017 - 09:19 AM

Just in all direction in general.

 

Ah, that's easier. I can prune out the directional compare functions, and test this for you. It reduces the power of weapons in general.

 

If you want it limited to a specific range of weapons, or any other specific mechanics, please detail them.

 

Somewhat anecdotal, but I have been thinking about adding Link->Defense[] to modify how weapons that strike Link affect him; but this will require some moderate rewrites of the Link class, to intercept weapons internally, and to define various procedures that run when a defence condition occurs.

 

I might think about modifying protection rings to add a reduction property, that, instead of dividing the power of weapons, reduces them by a set factor. That seems as if it would be relatively easy, but I may want to do it in a separate, and new item class; and all new item classes are scheduled for ZC 2.55. I want a pulse from the community on how disruptive these may be, for older quests, where the zzNNN classes might be in use.

 

I may need to add an extra set of classes, and change class from a  byte to a short, for this to work with no compatibility issues. (Groan.)

 

Anyway, what you want is pretty easy, and the code that I posted should do the trick, but I need to test it all. I recently finished preparing the test files for stunlock.zs, so I am a bit weary for the day. I may do it in an hour or two; else, tomorrow.

 

If you want to try it on your own, here is the revised code that ignores weapon direction.

int Z_Arr[256];

const itn SHIELD_DAMAGE_REDUCTION = 0;

void SetShieldDamageReduction(int amt) { Z_Arr[SHIELD_DAMAGE_REDUCTION] = amt; }
int GetShieldDamageReduction() { return Z_Arr[SHIELD_DAMAGE_REDUCTION]; }

const int EW_MISC_Z_FLAGS = 8;
const int EW_DAMAGE_REDUCED = 000010000b;

const int EW_DAMAGE_REDUCTION_DIST = 18;

const int I_DR_SHIELD = 100; //item ID of shield
 
//Attach this to the item as the pick-up script, and set D0 to a message, D1 to the damage reduction value.
//Picking up the item sets the global DR value.
item script DamageReductionShield
{
    void run(int msg, int amt)
    {
        if ( msg ) Screen->Message(msg);
        SetShieldDamageReduction(Abs(amt));
    }
}


bool DR_Shield_DistXY(eweapon b, int distance) {
    int distx; int disty;
    if ( Link->X > b->X ) distx = Link->X - b->X;
    else distx = b->X - Link->X;
    
    if ( Link->Y > b->Y ) disty = Link->Y - b->Y;
    else disty = b->Y - Link->Y;

    return ( distx <= distance && disty <= distance );
}


void ShieldReduction(int amt)
{
    eweapon ew; int numew = Screen->NumEWeapons();
    for ( ; numew > 0; numew-- )
    {
        ew = Screen->LoadEWeapon(numew);
        if ( ( ew->Misc[EW_MISC_Z_FLAGS]&EW_DAMAGE_REDUCED == 0 ) )
        {
            
            if ( DR_Shield_DistXY(ew, EW_DAMAGE_REDUCTION_DIST) )
            {
                ew->Damage -= amt;
                ew->Misc[EW_MISC_Z_FLAGS |= EW_DAMAGE_REDUCED;
            }
            
        }
    }
}

void DoShieldDamageReduction()
{
    if ( Link->Item[I_DR_SHIELD] ) { ShieldReduction(GetShieldDamageReduction()); } //Runs only if Link has the item.
}
//Example global script.
global script Shield_DR
{
    void run()
    {
        while(1)
        {
            DoShieldDamageReduction(); //Add this to your existing global active script, prior to waitdraw.
                                                            //It is best to call this *early* in the while loop,
                                                            //but after any other functions that create or modify eweapons.
            Waitdraw();
            
            Waitframe();
        }
    }
}

Edited by ZoriaRPG, 13 October 2017 - 09:30 AM.


#5 Deedee

Deedee

    Bug Frog Dragon Girl

  • Moderators
  • Real Name:Deedee
  • Pronouns:She / Her, They / Them
  • Location:Canada

Posted 13 October 2017 - 10:46 AM

            if ( DR_Shield_DistXY(ew, EW_DAMAGE_REDUCTION_DIST) )
            {
                ew->Damage -= amt;
                ew->Misc[EW_MISC_Z_FLAGS |= EW_DAMAGE_REDUCED;
            }

There's no closing bracket for ew->Misc.



#6 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 13 October 2017 - 12:36 PM



There's no closing bracket for ew->Misc.

 

Err, and, so there isn't. :D

 

That's why I run this stuff through testing phases.

 

Done, and tested:

 

Test Quest

 

I cheated, and I used an init script to give Link the item, and to set the values for the DR. THe item script, will of course work, and you should not use the Init script for deploying a quest with this.

//import "std.zh"

int Z_Arr[256]; //Global array for any of my code. -Z

//Array index.
const int SHIELD_DAMAGE_REDUCTION_VALUE = 0;
const int SHIELD_DAMAGE_REDUCTION_ITEM = 1;

//Accessors
void SetShieldDamageReduction(int amt) { Z_Arr[SHIELD_DAMAGE_REDUCTION_VALUE] = amt; }
int GetShieldDamageReduction() { return Z_Arr[SHIELD_DAMAGE_REDUCTION_VALUE]; }

void Set_DR_ShieldItem(int itm_id){ Z_Arr[SHIELD_DAMAGE_REDUCTION_ITEM] = itm_id; }
int Get_DR_ShieldItem(){ return Z_Arr[SHIELD_DAMAGE_REDUCTION_ITEM]; }

//EWeapon Misc Values
const int EW_MISC_Z_FLAGS = 8;

//EWeapon FLags
const int EW_DAMAGE_REDUCED = 000010000b;

//Settings
const int EW_DAMAGE_REDUCTION_DIST = 18;
const int I_DR_SHIELD = 100; //item ID of shield

void DrawDR_Shield_Aura(){} //Skleton function if you want to draw an aura effect.

// Attach this to the item as the pick-up script, and set :
// D0 to a message
// D1 to the damage reduction value.
// Picking up the item sets the global DR value.
item script DamageReductionShield
{
    void run(int msg, int amt)
    {
        if ( msg ) Screen->Message(msg);
    Set_DR_ShieldItem(I_DR_SHIELD);
        SetShieldDamageReduction(Abs(amt));
    }
}


bool DR_Shield_DistXY(eweapon b, int distance) {
    int distx; int disty;
    if ( Link->X > b->X ) distx = Link->X - b->X;
    else distx = b->X - Link->X;
    
    if ( Link->Y > b->Y ) disty = Link->Y - b->Y;
    else disty = b->Y - Link->Y;

    return ( distx <= distance && disty <= distance );
}


void ShieldReduction(int amt)
{
    eweapon ew; int numew = Screen->NumEWeapons();
    for ( ; numew > 0; numew-- )
    {
        ew = Screen->LoadEWeapon(numew);
        if ( ( (ew->Misc[EW_MISC_Z_FLAGS]&EW_DAMAGE_REDUCED) == 0 ) )
        {
            
        if ( DR_Shield_DistXY(ew, EW_DAMAGE_REDUCTION_DIST) )
        {
            ew->Damage -= amt;
            ew->Misc[EW_MISC_Z_FLAGS] |= EW_DAMAGE_REDUCED;
        }
            
        }
    }
}

void DoShieldDamageReduction()
{
    if ( Link->Item[Get_DR_ShieldItem()] ) { ShieldReduction(GetShieldDamageReduction()); } //Runs only if Link has the item.
}

global script Shield_DR
{
    void run()
    {
        while(1)
        {
            DoShieldDamageReduction(); //Add this to your existing global active script, prior to waitdraw.
                                                            //It is best to call this *early* in the while loop,
                                                            //but after any other functions that create or modify eweapons.
            Waitdraw();
            
            Waitframe();
        }
    }
}
 

Init Script Used for Testing

//An init script to test this code.
global script Init
{
    void run()
    {
        Link->Item[I_DR_SHIELD] = true;
        Set_DR_ShieldItem(I_DR_SHIELD);
        SetShieldDamageReduction(2);
    }
}

All of the code is also in the (test quest) script buffer.


Edited by ZoriaRPG, 13 October 2017 - 12:59 PM.


#7 FireSeraphim

FireSeraphim

    Behold the might of legend!

  • Members
  • Real Name:Patrick Casey Spurlock

Posted 13 October 2017 - 09:25 PM

Thank you.

#8 Mitsukara

Mitsukara

    Ara?

  • Members
  • Real Name:Jennifer

Posted 14 October 2017 - 04:05 PM

I don't know if you already have plans for the Peril Rings, but just to throw another vaguely related suggestion out there: you can make Peril Rings that always go into effect to reduce Link's damage by setting the 'Maximum Hearts' to the maximum collectible heart containers (or higher).

 

Not sure if that would help with any of your plans, but that's what I did for life levelups and guardian acorns (though with that I had a thing that adjusted the item's power via script, to use just one item and have it adjust it's strength based on the combination of those two factors.)



#9 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 14 October 2017 - 08:34 PM

I don't know if you already have plans for the Peril Rings, but just to throw another vaguely related suggestion out there: you can make Peril Rings that always go into effect to reduce Link's damage by setting the 'Maximum Hearts' to the maximum collectible heart containers (or higher).

 

Not sure if that would help with any of your plans, but that's what I did for life levelups and guardian acorns (though with that I had a thing that adjusted the item's power via script, to use just one item and have it adjust it's strength based on the combination of those two factors.)

 

You don't need Peril Rings for the GUardian Acorn effect, or for the Piece of Power effect.

 

I give Link a L1 ring, set in the item editor to L1, no CSet change, and a Damage Divisor of 0; then I increase the levels of the blue, red, and gold rings, respectively to 2, 3, and 4.

 

From there, I do this, for the Guardian Acorn effect:

void SetGuardianArcorn(bool on){
    int itm; itemdata id;
    itm =  GetHighestLevelItem(IC_RING);
    id = Game->LoadItemData(itm);
    if ( on ) id->Power = id->Power *2;
    else id->Power = id->Power * 0.5;
}

I likewise, do this for swords, with Pieces of Power. The function is called if the (global) status of each is false, and Link collects pieces of each, I set the global state true and run the function; thus calling DoGuardianAcron(true). When I end the effect, if the (global) state is true, I set the state false, and I call the same function, with a false parameter: DoGuardianAcron(false) .

 

The overall code looks like this:

 

Using peril rings would be self-defeating, as you can see, as using a L1 armour ring allows you to use GetHighestLevelitem() on that item class, and automate the affair with all armour levels.

 

Peril Rings were never meant for that kind of purpose. :D

 

In any case, Peril Rings also use a damage divisor, not a flat amount of damage reduction, which is what the OP wanted.


Edited by ZoriaRPG, 14 October 2017 - 08:35 PM.


#10 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 16 October 2017 - 03:33 AM

Here is a little update, as what I originally coded, was for a specific 'shielding' (passive) item. The foiginal code above works for that, but it was not what FS wanted. I envisioned his request applying to one, specific item, as I had done in a quest, for my aura shield spell, that granted a limited time barrier with its own HP, that soaked n damage per hit, until it was depleted either by soaking too much HP, or until the timer elapsed.

 

Here is a revision that works with up to four normal shield items, respects removing them (e.g., if they are eaten), and allows setting a differing value for each, using the value of the highest equipped.

 

import "std.zh"
//Shield Damage Reduction
//v2
//15th October, 2017
//ZoriaRPG

const int I_SHIELD4 = 100; //ID of Level 4 shield.

int Z_Arr[256]; //Global array for any of my code. -Z

//Array index.
const int SHIELD_DAMAGE_REDUCTION_VALUE = 0;
const int SHIELD_DAMAGE_REDUCTION_ITEM = 1;


int HardCodedShieldDamageReduction[8]={I_SHIELD1, 1, I_SHIELD2, 2, I_SHIELD3, 3, I_SHIELD4, 4};

void CheckSetCurrentShieldLevelAndValues(){
    int itm = DR_Shield____GetHighestLevelItemOwned(IC_SHIELD);
    if ( itm > -1 ) {
        //Link has some kind of shield. Figure out its stats:
        for ( int q = 0; q < 8; q++ )
        {
            if ( HardCodedShieldDamageReduction[q] == itm )
            {
                //match the shield item ID to what Link has.
                Set_DR_ShieldItem(itm);
                SetShieldDamageReduction(HardCodedShieldDamageReduction[q+1]);
            }
        }
    }
}

void DR_Debug(){
    if ( Link->PressEx1 )
    {
        int s[]="Presebt Shield Item Required: "; int ss[]="Present DR Amount :";
        TraceNL(); TraceS(s); Trace(Get_DR_ShieldItem());
        TraceNL(); TraceS(ss); Trace(GetShieldDamageReduction());
        
        Trace(DR_Shield____GetHighestLevelItemOwned(IC_SHIELD));
    }
    if ( Link->PressEx2 ) {
        itemdata id = Game->LoadItemData(93);
        Trace(id->Family);
    }
}
    
int DR_Shield____GetHighestLevelItemOwned(int itemclass)
{
    itemdata id;
    int ret = -1;
    int curlevel = -1;
    
    int items[256]; //holds the level of each item
    int levels[8];  //holds the item ID of each level (1 to 8)
    int i; int lv;
    int curitem = -1;
    //143 is default max items, increase if you add lots of your own
    for( i = 0; i <= 255; i++)
    {
        id = Game->LoadItemData(i);
        if(id->Family != itemclass)
            continue;
        
        items[i] = id->Level;
    }
    //Sort the ids of the levels
    for ( i = 0; i < 256; i++ )
    {
        if ( items[i] > 0 )
        {
            lv = items[i];
            levels[lv] = i;
        }
    }
    
    //Determine if Link owns any of the items in levels
    for ( i = 0; i < 8; i++ )
    {
        //Trace(levels[i]);
        if ( Link->Item[ levels[i] ] )
        {
            curitem = levels[i];
        }
    }
    return curitem;
}

//Accessors
void SetShieldDamageReduction(int amt) { Z_Arr[SHIELD_DAMAGE_REDUCTION_VALUE] = amt; }
int GetShieldDamageReduction() { return Z_Arr[SHIELD_DAMAGE_REDUCTION_VALUE]; }

void Set_DR_ShieldItem(int itm_id){ Z_Arr[SHIELD_DAMAGE_REDUCTION_ITEM] = itm_id; }
int Get_DR_ShieldItem(){ return Z_Arr[SHIELD_DAMAGE_REDUCTION_ITEM]; }

//EWeapon Misc Values
const int EW_MISC_Z_FLAGS = 8;

//EWeapon FLags
const int EW_DAMAGE_REDUCED = 000010000b;

//Settings
const int EW_DAMAGE_REDUCTION_DIST = 18;
const int I_DR_SHIELD = 100; //item ID of shield

void DrawDR_Shield_Aura(){} //Skleton function if you want to draw an aura effect.

// Attach this to the item as the pick-up script, and set :
// D0 to a message
// D1 to the damage reduction value.
// D2
// Picking up the item sets the global DR value.
item script DamageReductionShield
{
    void run(int msg, int amt, int item_id)
    {
        if ( msg ) Screen->Message(msg);
        
        for ( int q = 0; q < 8; q++ )
        {
            if ( HardCodedShieldDamageReduction[q] == item_id )
            {
                //match the shield item ID to what Link has.
                HardCodedShieldDamageReduction[q+1] = Abs(amt);
            }
        }
        Set_DR_ShieldItem(item_id);
    }
}


bool DR_Shield_DistXY(eweapon b, int distance) {
    int distx; int disty;
    if ( Link->X > b->X ) distx = Link->X - b->X;
    else distx = b->X - Link->X;

    if ( Link->Y > b->Y ) disty = Link->Y - b->Y;
    else disty = b->Y - Link->Y;

    return ( distx <= distance && disty <= distance );
}


void ShieldReduction(int amt)
{
    eweapon ew; int numew = Screen->NumEWeapons();
    for ( ; numew > 0; numew-- )
    {
        ew = Screen->LoadEWeapon(numew);
        if ( ( (ew->Misc[EW_MISC_Z_FLAGS]&EW_DAMAGE_REDUCED) == 0 ) )
        {
            
            if ( DR_Shield_DistXY(ew, EW_DAMAGE_REDUCTION_DIST) )
            {
                ew->Damage -= amt;
                ew->Misc[EW_MISC_Z_FLAGS] |= EW_DAMAGE_REDUCED;
            }
            
        }
    }
}

void DoShieldDamageReduction()
{
    if ( Link->Item[Get_DR_ShieldItem()] ) { ShieldReduction(GetShieldDamageReduction()); } //Runs only if Link has the item.
}

global script Shield_DR
{
    void run()
    {
        while(1)
        {
        
            CheckSetCurrentShieldLevelAndValues();
            DR_Debug();
            DoShieldDamageReduction(); //Add this to your existing global active script, prior to waitdraw.
                                                            //It is best to call this *early* in the while loop,
                                                            //but after any other functions that create or modify eweapons.
            Waitdraw();
        
            Waitframe();
        }
    }
}




Also tagged with one or more of these keywords: Item Script, Request

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users