Page 1 of 1

Armor Ignore Concept

Posted: Sat Jun 19, 2021 10:13 pm
by dragon slayer
function AbilitiesRegistration()
{
    RegisterAbilitie(1, true);  // say, Armor Ignore, same as in the Abilities.dfn file
}

function onSpecialMove(pUser, abilityID)
{
    switch (abilityID)
    {
        case 0x01: // Armor Ignore
            HandleArmorIgnore(pUser, abilityID);
            break;
        default:
            break;
    }
    return true;
}

function CheckMana(pUser, mAbility, abilityID)
{
    var mAbility = Abilitie[abilitieNum];

    if (pUser.mana <= mAbility.mana)
    {
        pUser.TextMessage("You need " + mAbility.mana + " mana to perform that attack"); // 1060181 mana.ToString() You need ~1_MANA_REQUIREMENT~ mana to perform that attack
        DeactivateSpecialMove(pUser.socket, abilityID);
        return false;
    }
    else
        pUser.mana - mAbility.mana;
    return true;
}

function HandleArmorIgnore(pUser, abilityID)
{
    pUser.SetTag("ArmorIgnore", true);
}

function onCombatDamageCalc(pAttacker, pDefender, fightSkill, hitLoc)
{
    var baseDamage = pAttacker.attack;

    if (baseDamage == -1)  // No damage if weapon breaks
        return 0;

    var damage = ApplyDamageBonuses(1, pAttacker, pDefender, fightSkill, hitLoc, baseDamage);

    if (damage < 1)
        return 0;

    // Check if attacker has armor ignore enabled
    if (!pAttacker.GetTag("ArmorIgnore"))
    {
        // Armor Ignore ignores defense modifiers, but deals only 90% of potential damage
        damage *= 0.9;

        if (fightSkill == 31) // Archery
        {
            // Cap damage from Armor Strike attack at 30 for archery weapons
            if (damage > 30)
                damage = 30;
        }
        else {
            // For all othe rfighting skills, cap damage from Armor Strike at 35
            if (damage > 35)
                damage = 35;
        }
    }
    else {
        // Otherwise, apply normal defense modifiers
        damage = ApplyDefenseModifiers(1, pAttacker, pDefender, fightSkill, hitLoc, damage, true);
    }

    // If damage after defense modifiers is below 0, do a small random amount of damage still
    if (damage <= 0)
        damage = RandomNumber(0, 4);

    // If defender is a player, damage is divided by this modifier from uox.ini
    if (!pDefender.npc)
        damage /= GetServerSetting("NPCDAMAGERATE");

    return damage;
}

function onAttack(pAttacker, pDefender, abilityID)
{
    if (pAttacker.GetTag("ArmorIgnore"))
    {
        if (!CheckMana(pUser, mAbility, abilityID))
            return true;

        pAttacker.TextMessage("Your attack penetrates their armor!");
        pDefender.TextMessage("The blow penetrated your armor!");

        pDefender.SoundEffect(0x0056, true);
        pDefender.StaticEffect(0x3728, 0x09, 0x06);
        DeactivateSpecialMove(pAttacker.socket, abilityID);
        pAttacker.SetTag("ArmorIgnore", false);
    }
}

function DeactivateSpecialMove(pSocket, abilityID)
{
    var toSend = new Packet;
    toSend.ReserveSize(7)
    toSend.WriteByte(0, 0xbf); // Packet
    toSend.WriteShort(1, 0x07); // Length
    toSend.WriteShort(3, 0x21); // SubCmd
    toSend.WriteByte(5, abilityID); // Ability ID
    toSend.WriteByte(6, 0); // On/off
    pSocket.Send(toSend);
    toSend.Free();
}

function onTimer(timerObj, timerID)
{
    //Toggle ability off after 5 second timer has elapsed
    var toSend = new Packet;
    toSend.ReserveSize(7)
    toSend.WriteByte(0, 0xbf); // Packet
    toSend.WriteShort(1, 0x07); // Length
    toSend.WriteShort(3, 0x21); // SubCmd
    toSend.WriteByte(5, timerID); // Ability ID
    toSend.WriteByte(6, 0); // On/off
    timerObj.socket.Send(toSend);
    toSend.Free();
}
// ENABLE: 0 - No, 1 - Yes                    
// MANA: Mana Cost                  
// SKILLPOINTS skill points needed to use the abilities

// Armor Ignore
[Ability 1]
{
NAME=Armor Ignore
ENABLE=1
MANA=4
SKILLPOINTS=70
}
This would make abilities act similar to spells.dfn so users could easily mod them without having js coding.

I am sure the code can be added more two but i wanted to get a example how this could work.

Re: Armor Ignore Concept

Posted: Sun Jun 20, 2021 11:00 am
by Xuri
I think this looks like a decent approach to take for an initial setup of special moves/abilities. A couple of notes, though:

The AbilitiesRegistration part would not be required, as we're relying on the onSpecialMove event (which is triggered directly from the incoming packets from client). Same for the onTimer event, unless you want to start a timer somewhere to make sure it times out if user doesn't make use of the special move within X seconds.

In the CheckMana() function, you currently check if pUser's mana is below OR equal to the mana required for the ability. This means even if the player has exactly the amount of mana required, they would not be able to use the special move. Check for below only.

In the same function, where you subtract the user's mana, it doesn't actually do that. You have:
pUser.mana - mAbility.mana;
but you need
pUser.mana -= mAbility.mana;

The onAttack JS event doesn't take a return value, so you can do a normal return without specifying true or false.

Also in onAttack JS event, TextMessages are used to display messages about the special move, but it should probably use SysMessage instead. Just make sure to check whether pAttacker and pDefender have valid sockets before attempting to send them a sysmessage. Like this:
if( pAttacker.socket != null )
    pAttacker.SysMessage( "Your attack penetrates their armor!" );
if( pDefender.socket != null )
    pDefender.SysMessage( "The blow penetrated your armor!" );

For the Abilities DFN setup, initial setup looks good, but the next step there before we implement anything should be to go over all the special moves and see what tweakable properties they have in common that we can put in as properties in the DFN, or if there are some we can put in to increase the flexibility of the system (for customization purposes). Like... we could add optional STAMINA or HEALTH costs in addition to MANA, and add an optional TACTICS requirement (https://www.uoguide.com/Special_Moves mentions that Tactics was added as a requirement in Publish 46). If a special ability has something very unique about it that would be hard to specify as a property tweakable in the DFN, we should probably not include an option for it, but just handle it in the JS files.