301 Days

A year of gamedev experiments.

Day 79 - Shielded Resistance

| Comments

In which we offer some temporary resistance.

Test Every Day

What’s next?

DragonsSpine/GameSystems/Effects/Effect.cslink
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    Shield,
    Regenerate_Hits,
    Regenerate_Mana,
    Regenerate_Stamina,
    Protection_from_Fire, // 40
    Protection_from_Cold,
    Protection_from_Poison,
    Protection_from_Fire_and_Ice,
    Protection_from_Blind_and_Fear,
    Protection_from_Stun_and_Death, // 45
    Resist_Fear,
    Resist_Blind,
    Resist_Stun,
    Resist_Lightning,
    Resist_Death, // 50
    Resist_Zonk,

Lots of resistance and protection stuff. We’ll take care of shielding first:

features/player_effects.featurelink
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
## Shield

# Notes:
# Temporary character attribute "Shielding"; there is a Land.MaxShielding.
# Land max is 9 in the current db.
# Visible via command 'show effects' as "Total Shielding = <value>".
# Value is subtracted from armor class for ranged attacks, half for melee.

Scenario: Temporary shield potion increases shield temporarily
    Given I use the "minimal" database as-is
    And I add player and character "TestTS02"
    And I create a "shield" potion of amount "5" and duration "2"
    And I put the item in the character's left hand
    And I start the server and play
    And I have a shielding of "0"
    When I open and drink "bottle"
    Then I have a shielding of "5"
    And I rest
    And I have a shielding of "0"

Scenario: Temporary shield potion maxes out at Land max
    Given I use the "minimal" database as-is
    And I add player and character "TestTS03"
    And I create a "shield" potion of amount "10" and duration "2"
    And I put the item in the character's left hand
    And I start the server and play
    And I have a shielding of "0"
    When I open and drink "bottle"
    Then I have a shielding of "9"
    And I rest
    And I have a shielding of "0"

Rather than starting a fight, I’m just using the “show effects” command to see what the effect is. Everything works well until I try multiple potions on a whim, and instead of combining or overriding, the effect drops to zero..? Couldn’t immediately figure it out, so tag the test and move on.

features/player_effects.featurelink
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
# bug - rather than having the amount updated, we wind up with 0?
@bug
Scenario: Multiple temporary shield potions
    Given I use the "minimal" database as-is
    And I add player and character "TestTS04"
    And I create a "shield" potion of amount "6" and duration "99"
    And I put the item in the character's right hand
    And I create a "shield" potion of amount "9" and duration "99"
    And I put the item in the character's left hand
    And I start the server and play
    And I have a shielding of "0"
    When I open and drink "bottle"
    Then I have a shielding of "6"
    And I drop "right"
    And I open and drink "bottle"
    And I have a shielding of "9"

For the protection and resistance stuff, let’s make some generic steps:

features/steps/character_steps.rblink
384
385
386
387
388
389
390
391
392
393
394
Then(/^I have a "([^"]*)" resistance of "([^"]*)"$/) do |type, desired_value|
  resp = telnet_command(@connection, "show resists", / ->/)
  waited_for = /#{type}\s*:\s*#{desired_value}\b/i
  expect(@last_resp).to match(waited_for)
end

Then(/^I have a "([^"]*)" protection of "([^"]*)"$/) do |type, desired_value|
  resp = telnet_command(@connection, "show protection", / ->/)
  waited_for = /#{type}\s*:\s*#{desired_value}\b/i
  expect(@last_resp).to match(waited_for)
end
features/player_effects.featurelink
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
## Resistance and Protection effects
# TODO - verify no unintended resistance/protection
Scenario Outline: Resistance and protection potions have desired effects
    Given I use the "minimal" database as-is
    And I add player and character "TestRP01"
    And I create an "<effect>" potion of amount "<amt>" and duration "3"
    And I put the item in the character's left hand
    And I start the server and play
    And I have a "<resist>" resistance of "0"
    And I have a "<protect>" protection of "0"
    When I open and drink "bottle"
    And I have a "<resist>" resistance of "<resistamt>"
    And I have a "<protect>" protection of "<protectamt>"
    And I rest
    And I have a "<resist>" resistance of "0"
    And I have a "<protect>" protection of "0"
Examples:
| effect                         | amt | resist    | resistamt | protect | protectamt |
| Protection_from_Fire           | 2   | Fire      | 1         | Fire    | 2          |
| Protection_from_Cold           | 3   | Ice       | 1         | Ice     | 3          |
| Protection_from_Fire_and_Ice   | 4   | Fire      | 1         | Fire    | 4          |
| Protection_from_Fire_and_Ice   | 5   | Ice       | 1         | Ice     | 5          |
| Protection_from_Poison         | 6   | Poison    | 1         | Poison  | 6          |
| Protection_from_Stun_and_Death | 8   | Death     | 1         | Death   | 8          |
| Protection_from_Stun_and_Death | 9   | Stun      | 1 | | |
| Protection_from_Blind_and_Fear | 7   | Blind     | 1 | | |
| Protection_from_Blind_and_Fear | 8   | Fear      | 1 | | |
| Resist_Fear                    | 7   | Fear      | 1 | | |
| Resist_Blind                   | 0   | Blind     | 1 | | |
| Resist_Stun                    | 5   | Stun      | 1 | | |
| Resist_Lightning               | 0   | Lightning | 1 | | |

Resist_Death seems to have an interesting issue. In CreateCharacterEffect:

DragonsSpine/GameSystems/Effects/Effect.cslink
807
808
809
    case EffectType.Resist_Death:
        target.DeathResistance++;
        break;

But in StopCharacterEffect:

DragonsSpine/GameSystems/Effects/Effect.cslink
537
538
539
    case EffectType.Resist_Death:
        this.target.DeathProtection -= effectAmount;
        break;

So we’ll split that off into a separate test and bug-tag it until it’s fixed:

features/player_effects.featurelink
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
# bug? - Resist_Death adds death resistance but removes death protection when it wears off
# NOTE: Merge with other test when fixed.
@bug
Scenario Outline: Death resistance potion has desired effect
    Given I use the "minimal" database as-is
    And I add player and character "TestRP02"
    And I create an "<effect>" potion of amount "<amt>" and duration "3"
    And I put the item in the character's left hand
    And I start the server and play
    And I have a "<resist>" resistance of "0"
    And I have a "<protect>" protection of "0"
    When I open and drink "bottle"
    And I have a "<resist>" resistance of "<resistamt>"
    And I have a "<protect>" protection of "<protectamt>"
    And I rest
    And I have a "<resist>" resistance of "0"
    And I have a "<protect>" protection of "0"
Examples:
| effect                         | amt | resist    | resistamt | protect | protectamt |
| Resist_Death                   | 3   | Death     | 1 | | |

Zonk?

I initially skipped over it; what the heck is Resist_Zonk?

In the DoDamage method, we find:

DragonsSpine/GameSystems/Rules/Rules.cslink
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
 if (target.Stunned <= 0 && critical && !target.immuneStun)
  {
        int saveMod = -(target.ZonkResistance);
        // damager used a bash
        if (damager.CommandType == Command.CommandType.Bash)
        {
            saveMod += Math.Max(target.Level, Skills.GetSkillLevel(damager.GetSkillExperience(Globals.eSkillType.Bash))) -
                Math.Min(target.Level, Skills.GetSkillLevel(damager.GetSkillExperience(Globals.eSkillType.Bash)));
        }

        if (!DND_GetSavingThrow(target, SavingThrow.PetrificationPolymorph, saveMod))
        {
            // stun for 1 round if bash save failed, 1 - 2 for others
            if (damager.CommandType == Command.CommandType.Bash)
                target.Stunned = 1;
            else target.Stunned += (short)RollD(1, 2);

It also partially protects from spell-based stuns. But then what does StunResistance do?

DragonsSpine/GameSystems/Rules/Rules.cslink
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
    case "stun":
        #region Immune to Stun
        if (target.immuneStun)
        {
            if (caster != null)
            {
                if (target.race != "")
                {
                    caster.WriteToDisplay(target.Name + " is immune to stun based magic.");
                }
                else
                {
                    caster.WriteToDisplay("The " + target.Name + " is immune to stun based magic.");
                }
            }
            return 0;
        }
        #endregion
        else if (DND_GetSavingThrow(target, savingThrow, -(target.StunResistance) + casterSL))
        {
            if (caster != null)
            {
                if (target.race != "")
                {
                    caster.WriteToDisplay(target.Name + " resists your Stun spell.");
                }
                else
                {
                    caster.WriteToDisplay("The " + target.Name + " resists your Stun spell.");
                }

So StunResistance is just for a “stun” spell, and ZonkResistance is for all other ways you might get stunned. Interesting. I guess I should add a test for ZonkResistance.

…which fails. Turns out it’s an effect for worn items only, even if I make a potion for it. I’ll have to tackle the worn effect thing, once I’ve exhausted all the potioning. Tomorrow.


Interesting Stuff


Day 79 code - tests

Comments