Sunday, November 10, 2024

Is Conjure Elementals Really Broken


Does Conjure Minor Elementals damage apply to multi target cantrips like Eldritch Blast?


Hi all,

Treantmonk a prominent YouTuber recently did a video (recent as in the last 3 months 😊) on how the spell Conjure Minor Elementals breaks the game of D&D. I think he may be interpreting the rules incorrectly.

Now the basis of his argument centres around the example of a valor bard build with a one level dip in warlock.

The Warlock dip is to access Eldritch Blast cantrip and the Valor Bard is because Conjure Minor Elements is not natively on the bard spell list, but they can grab it at level 10 with the Magical Secrets feature, and they get the cantrip Shillelagh also. The valor subclass can also, at level 6, if they take the attack action, they can swap out an attack from the Extra Attack feature with a cantrip.

To set up the whole thing, the bard is using the cantrip Shillelagh to make their attacks and then swap out an extra attack to cast Eldritch Blast, and since their initial attack (using shillelagh) uses a club, which is a light weapon, that allows an extra off hand attack with the bonus action, with another light weapon.

At the end of all of this, at level 11, the Valor Bard 10/Warlock 1 gets 6 attacks per turn and with Conjure Minor Elementals up and running (Plus 4d8 extra damage) they get six attacks per turn.

• 3 from Eldritch Blast
• 1 from the club attack via Shillelagh
• and 1 from the light weapon bonus attack

Or do they?

My argument is that that bard/Warlocks only gets 3 attacks, they make 6 attack rolls but only 3 attacks.

That is, Eldritch Blast as a cantrip give one attack within the meaning of the rules even as it gives multiple attack rolls. There is a reason that the rules glossary distinguishes between an attack and an attack roll.

First let’s look at the relevant text of the spells in question:

"Shillelagh

Transmutation Cantrip (Druid)
Casting Time: Bonus Action
Range: Self
Components: V, S, M (mistletoe)
Duration: 1 minute

A Club or Quarterstaff you are holding is imbued with nature’s power. For the duration, you can use your spellcasting ability instead of Strength for the attack and damage rolls of melee attacks using that weapon, and the weapon’s damage die becomes a d8. If the attack deals damage, it can be Force damage or the weapon’s normal damage type (your choice).

The spell ends early if you cast it again or if you let go of the weapon.

Cantrip Upgrade. The damage die changes when you reach levels 5 (d10), 11 (d12), and 17 (2d6).
"

Ok, this seems to be ok and allows the Attack Action to be conducted using Shillelagh and since the character has Extra Attack, they can make 2 attacks in a turn plus a bonus attack with a light weapon on turns other than the one they cast Shillelagh.

So far, so good, what about Eldritch Blast?

"Eldritch Blast

Evocation Cantrip (Warlock)
Casting Time: Action
Range: 120 feet
Components: V, S
Duration: Instantaneous

You hurl a beam of crackling energy. Make a ranged spell attack against one creature or object in range. On a hit, the target takes 1d10 Force damage.

Cantrip Upgrade. The spell creates two beams at level 5, three beams at level 11, and four beams at level 17. You can direct the beams at the same target or at different ones. Make a separate attack roll for each beam.

"


Here there is some interesting wording. The Casting time is one action but not terribly relevant since the level six Extra attack feature allows the substitution of a cantrip for one of these attacks.

Eldritch Blast however in the main body refers to the cantrip making a ranged spell attack as the effect of the spell but the extra beams are not referred to as separate attacks but as attack rolls. My view is that the cantrip only counts as a single attack, even if directed at multiple targets.

Now looking at Conjure Minor Elementals and the glossary definitions of Attack and Attack Rolls:


CONJURE MINOR ELEMENTALS

Level 4 Conjuration (Druid, Wizard)
….
You conjure spirits from the Elemental Planes that flit around you in a 15-foot Emanation for the duration. Until the spell ends, any attack you make deals an extra 2d8 damage when you hit a creature in the Emanation. This damage is Acid, Cold, Fire, or Lightning (your choice when you make the attack).
…..”

The relevant section of this spell is bolded, it adds the damage to any attack.

Now for the rules of the attack action and attack roll.

When you take the Attack action, you can make one attack roll with a weapon or an Unarmed Strike. …….

An attack roll is a D20 Test that represents making an attack with a weapon, an Unarmed Strike, or a spell. See also chapter 1 (“D20 Tests”).”

There is distinction drawn between Attack and Attack Rolls, what does the general rules say about making an attack.

"Making an Attack

When you take the Attack action, you make an attack. Some other actions, Bonus Actions, and Reactions also let you make an attack. Whether you strike with a Melee weapon, fire a Ranged weapon, or make an attack roll as part of a spell, an attack has the following structure: ….."

This would seem to imply that a spell that makes an attack roll is an attack for the purposes of the general procedures of the game. So Eldritch Blast is an Attack for the purposes of CME but what about the beams?

it also implies that the Extra Attack feature confers an attack.

Well, here I want to look at what Hunter’s Mark and Hex have to say – Which was what triggered my thoughts on this matter).

"Hunter’s Mark

Level 1 Divination (Ranger)….You magically mark one creature you can see within range as your quarry. Until the spell ends, you deal an extra 1d6 Force damage to the target whenever you hit it with an attack roll. You also have Advantage on any Wisdom (Perception or Survival) check you make to find it….

Hex

……You place a curse on a creature that you can see within range. Until the spell ends, you deal an extra 1d6 Necrotic damage to the target whenever you hit it with an attack roll. Also, choose one ability when you cast the spell. The target has Disadvantage on ability checks made with the chosen ability……"

These spells specifically call out attack rolls, so the would apply to a spell like Eldritch blast but they do not use the word attack like Conjure Minor Elementals does.

With all of this considered I believe that Conjure Minor Elementals only adds damage to an attack and that Eldritch Blast or any other multi-target cantrip is only a single attack for the purposes of this spell. Otherwise, why make the distinction in the Eldritch Blast spell between the Attack in the body of the spell but refer to the extra beams as “Attack Rolls” and to refer to the damage in Hunter’s Mark and in Hex as applying to the “Attack Rolls”.

So, in the linked video, at 9 minutes in the CME damage was calculated at 90, 5 attacks with an additional 4d8 => 4.5*5= 18 per attack for a total of 90 extra damage.

My argument is that this damage should be only added 3 times.

Once for the cantrip, once for the club attack and once for the bonus light weapon attack.

For a total of 54 which is still very good but not as broken as the 90 and it is only going to scale with the level slot used to cast the spell, not with that and the number of beams supplied by Eldritch Blast.

What do people think? is my reasoning too convoluted? Have I completely missed the point.

Let me know in the comments.

Even if you do not agree that my interpretation is correct "Rules as written", I think it would a good ruling to make before trying out other nerfs.

Saturday, November 9, 2024

 

Change of topics

Greeting all,

This blog was a place where I used to keep some lessons learned from various task that gave some trouble in my software career.

Now, I am retired from that, and I want to write something about games and Dungeons and Dragons.

So I will be mostly posting on that an other gaming topics that I want to get off my chest.

UngainlyTitan

Thursday, October 7, 2010

A look at Entity Framework

What I have been doing since.

Been a while since I posted here. Blame real life and some computer issues. Purchased a new laptop as spring with the intension of it being my new development machine and that I would make more use of virtual machines and such tricks.
For the last month it has been unavailable to me as it was randomly crashing. I have been on the phone with Dell tech support several times for hours on end the issue is still unresolved but meanwhile I returned to my old  machine which in spite of making the occasional funny fan noise it is still soldiering on. I rebuilt my database server on another machine and need to look into backup solutions as my 1TB NAS disk is filling up faster than I would like.

Exploration of Entity Framework

One of the things I have been researching recently is Entity Framework, this is mainly because i have been considering of applying it to a project i have been working on. However, I have noticed a couple of things on my explorations on the web; most of the code is in C# and the examples are either, trivial or very complex. So after some research I have decided to purchase a book. In general I think to learn better from books if I need more in-depth knowledge. So I choose “Entity Framework 4.0 Recipes – A problem-Solution Approach” by Larry Tenny and Zeeshan Hirani. Of course it is written in C#, one wonders is there a deliberate policy of deprecating vb.net or do they simply consider that all serious programmers are using C#. Anyway I decide it would be fun for me to rewrite all the listings in vb.net. This would serve two purposes; it would consolidate my knowledge of C# and learn some new tricks in vb.net. I even emailed Apress asking permission to list here, the vb.net translations of the code listings in the book (Never heard anything back – so I guess I won’t go there).
So far I have just completed chapter 2 which covers various scenarios concerning the way different database table structures could be modelled in the Entity Framework. Chapter 2 covers the following scenarios:
  • Creating a simple model
  • Creating a model from an Existing database
  • Modelling a Many to Many relationship with no payload
  • Modelling a Many to Many Relationship with a payload
  • Modelling a Self-Referencing Relationship
  • Splitting a Entity across multiple Tables
  • Splitting a Table across multiple Entities
  • Modelling Table per Type inheritance
  • Using Conditions to filter an ObjectSet
  • Modelling Table per Hierarchy inheritance
  • Modelling Is-a and Has-a relationships between two Entities
  • Creating, Modifying and Mapping Complex Types.
One tool that I have found invaluable is a C# to VB convertor. The content is pretty clear and gives the step by step instructions to complete the tasks. All the code examples are console applications and so far the code to write data to the database and retrieve the data and display the returned data in the console, are given in the listing for each section.
Now I am not going to create tutorials on Entity Framework. I don’t yet know enough about the topic and the basics are well covered on MSDN, what I intend to do in this and future posts is create a guide to the “Entity Framework Recipes” book mentioned above. So basically I’ll list the topics covered in a chapter and include some code, the original C# listing and my vb.net translation.
So if we take the data tables shown in  below.Tables used in example
So the business table is a base set of information and the Retail and eCommerce tables hold additional information that relate to that type of business.



When you initially create a new Entity Framework mapping you get a similar set of entities.
Initial Entity Framework mapping

Here we have the same tables as Entities in the Entity Framework mapping created by default. The relationships will be edited  and replaced by inheritance relationships.
Delete the existing relationships and replace with inheritance relationships. Also remove the primary key entries in the inherited entities and then check that the mappings are still correct.



The final version of the used in the application looks like this.
Entity Framework Final Mapping
The C# code listing to write the data to the database and then retrieve it and display it to the console looks like the following code.
          using (var context = new EFRecipesEntities())
            {
                var business = new Business
                {
                    Name = "Corner Dry Cleaning",
                    LicenseNumber = "100x1"
                };
                context.Businesses.AddObject(business);
                var retail = new Retail
                {
                    Name = "Shop and Save",
                    LicenseNumber = "200C",
                    Address = "101 Main",
                    City = "Anytown",
                    State = "TX",
                    ZIPCode = "76106"
                };
                context.Businesses.AddObject(retail);
                var web = new eCommerce
                {
                    Name = "BuyNow.com",
                    LicenseNumber = "300AB",
                    URL = "www.buynow.com"
                };
                context.Businesses.AddObject(web);
                context.SaveChanges();

            }
            using (var context = new EFRecipesEntities())
            {
                Console.WriteLine("\n--- All Businesses ---");
                foreach (var b in context.Businesses)
                {
                    Console.WriteLine("{0} (#{1})", b.Name, b.LicenseNumber);

                }
                Console.WriteLine("\n--- Retail Businesses ---");
                foreach (var r in context.Businesses.OfType<Retail>)
                {
                    Console.WriteLine("{0} (#{1})", r.Name, r.LicenseNumber);
                    Console.WriteLine("{0}", r.Address);
                    Console.WriteLine("{0}, {1} {2}", r.City, r.State, r.ZIPCode);

                }
                Console.WriteLine("\n--- eCommerce Businesses ---");
                foreach (var e in context.Businesses.OfType<eCommerce>)
                {
                    Console.WriteLine("{0} (#{1})", e.Name, e.LicenseNumber);
                    Console.WriteLine("Online address is: {0}", e.URL);
                }
            }
        



The same code in VB.Net



  Using context As New EFRecipesEntities
            Dim business = New  Business  With {.Name = "Corner Dry Cleaning", _
                                              .LicenseNumber = "100x1"}
            context.Businesses.AddObject(business)
            Dim retail = New  Retail  With {.Name = "Shop and Save", _
                                          .LicenseNumber = "200C", _
                                          .Address = "101 Main", _
                                          .City = "Anytown", .State = "TX" _
                                         , .ZIPCode = "76106"}
            context.Businesses.AddObject(retail)
            Dim  web = New  eCommerce  With {.Name = "BuyNow.com", _
                                          .LicenseNumber = "300AB", _
                                          .URL = "www.buynow.com"}
            context.Businesses.AddObject(web)
            context.SaveChanges()

        End Using
        Using  context = New  EFRecipesEntities
            Console.WriteLine(ControlChars.Lf & "--- All Business ---")
            For Each b In context.Businesses
                Console.WriteLine("{0} (#{1})", b.Name, b.LicenseNumber)

            Next
            Console.WriteLine(ControlChars.Lf & "--- Retail Business ---")
            For Each r In context.Businesses.OfType(Of Retail)()
                Console.WriteLine("{0} (#{1})", r.Name, r.LicenseNumber)
                Console.WriteLine("{0}", r.Address)
                Console.WriteLine("{0}, {1} {2}", r.City, r.State, r.ZIPCode)
            Next
            Console.WriteLine(ControlChars.Lf & "--- eCommerce Business ---")
            For Each e In context.Businesses.OfType(Of eCommerce)()
                Console.WriteLine("{0} (#{1})", e.Name, e.LicenseNumber)
                Console.WriteLine("Online address is: {0}", e.URL)
            Next
        End Using
  

Thursday, June 24, 2010

A funny thing about Web Services in Visual Studio 2010

As mentioned in my profile, my primary activity these days is caring for mother but I have a couple of projects on the go as well when I get the chance to code. One of these project is porting a previous project to VB.NET 2010, party to learn 2010, partly to take advantage of some of the .NET 4.0 technologies to make the application more maintainable and efficient.

So far I have managed to port over all the source code and the existing NUnit tests, converting the NUnit tests to MSUnit Test as I go. So I had all my unit test running (or so I thought, it turns out I had missed some) and I tried running the application. So splash screen appears and login then I select one of the user screen from the main menu and bang! the application crashes.

The application has a dependency on Adobe Reader in several screens and Adobe does not  play well in 64bit environments. So then I get that working by setting the target CPU to x86 and now I can open the application view the screens but now there is no data on several. It turns out that the Web Services are throwing errors.

WebServiceError

So I googled the error and got a lot of info on checking that the .asmx file markup refers to the correct namespace and the code behind class is correctly named, also that the namespaces match. All of this I played around to no effect but of the 3 services one was working.

To no avail, it turns out that the code behind should be in an App_Code folder, even though Visual Studio did not create one when I created the .asmx file.

Must play around with this  some more.

Wednesday, June 9, 2010

For the Next Time I am moving a SQL Database to another server

Not a lot to comment on this; there is a good discussion here but the key bits to lookup on Books Online are:

The stored proceedure sp_change_users_login, look up the topic Troubleshooting Orphaned Users and the proceedure sp_validatelogins. That should be enough to get it all working when I need to to do it about 2 to 3 years as that seems to be the pattern of these things.

Tuesday, May 25, 2010

The Joy of HTML

Or more precisely the joy of xhtml, Now I had a website back in the mid nineties. it is long defunct though I still have the files, having found them on an old drive I rehabilitated recently. More specifically I am using “HTML4 for Dummies” by Ed Tittel and Stephen Nelson Jame and also “HTML, XHTML & CSS” by Ed Tittel and Jeff Noble. The site is for my brothers mountaineering web site; He manages most of his activities through face book and email.
So he wanted a simple page, with very little configuration, allowing contact but protecting his email from spam harvesters. The page is pure HTML and CSS for layout. So far, we are still tweaking it. it looks good on IE8 and Firefox. I still need to check on it in Safari on the iphone and the Palm Pre.
To hide the mail I used the catchpa service provided by Google called MailHide. By default this produces an email address that looks like “nam…@domain.com” with the ellipsis providing the link. Clicking on the link opens a pop up window that has the captcha and solving this reveals the email as an embedded mailto: link.  Since we did not like this we edited the generated code to replace the ellipsis with an image and removed the remaining original text of the email address.
The other problem, I have is with the Facebook like button. Here I was getting a popup window with error and nothing else much, no error message or anything of help. Some Googling later got me to this blog entry which I hope will solve the issue. I have to test that part yet.
Turns out that the problem (may have been blindness on my part since I did not see the textbox to enter the url for the site hosting the like button. It all seems to be working now. Firefox allows one to see who has liked the site but IE8 does not.

Tuesday, April 13, 2010

The Mocks are Mocking me.

A few years ago I heard about the idea of mock testing and tried to apply it to my code. I choose to use the DotNetMock framework because it worked in a way that I could get my head around. However, my approach begged a few questions as was a lot of work. It was pretty close to the older way of working with mocks where people code the mocks and the stubs and so forth, (for a good introduction of what that is all about see Martin Fowler's article
'Mocks aren't Stubs'. So now, I decide to refractor the code to improve performance and to do it with Visual Basic 2010 using the MSUnitTest framework. So I have already posted about converting from NUnit to MSUnitTest. So adding in the DotNetMock stuff should be a piece of cake, right? Just reference the DotNetMock.dll and away you go. Not so, I try that and I get an error in the tests.
Test method TestMasterList.TestAssemblies.TestGetNewCode threw exception:

System.TypeInitializationException: The type initializer for 'DotNetMock.Assertion' threw an exception. ---> System.SystemException:
Cannot find an appropriate test framework implementation.
At this point I search around for an alternative testing framework for Mock testing and the biggest buzz seems to be about
Rhino.Mocks and TypeMock however, the latter is a commercial product. So the problems are; most of the examples are in C#, they make extensive use of lambda expression and what I can find in vb use an older syntax for the mock code. Now, I know nearly nothing about lambda expressions, part of the reason for this exercise is to learn some of the new shiny stuff that has come out over the last 4 or 5 years by refactoring the code to take advantage of this stuff and get some improvement in performance. To do that I want to know my existing tests are working. So I try to learn Rhino.Mocks and start a new project to do it. I decide to implement a view model controller in windows forms with a passive view and the view communicating to the controller using events. The test is failing for reasons that are unclear to me and I have posted to the Google Group (aka Usenet) Rhino.Mocks with this post
So meanwhile while I try to learn Rhino.Mocks and lambda syntax what do I do. DotNetMock is defunct as far as I can tell and from what I have seen in Rhino and other mocking frameworks, it was a dead end approach anyway. However, I have code that uses that approach and I need to get those tests to run. So I decided to create my own replacement for the element of DotNetMock that I use. Essentially I used the DotNetMock.Mock class and the ExpectationCounter. When I created a mock class I inherited from the base DotNetMock.Mock class so that i could use the Verify method to determine that the expectations I had set had been fulfilled. Now expectations were set using the ExpectationCounter as a member level variable in Mock class.
To give an example; for the interface IFoo declared below


    Public Interface IFoo

       Sub SomeMethod()

    End Interface

In the DotNetMock style this would be implemented as a mock class thus;

    Public Class MockFoo

       Implements IFoo
       Private _ExpectSomeMethodCall as New ExpectationCounter("SomeMethod")



       Public Sub SetExpectationOnSomeMethod(ByVal expectedCalls as integer)

          _ExpectSomeMethodCall.Expect = expectedCalls

       End Sub

       Public Sub SomeMethod() Implements IFoo.SomeMethod

          _ExpectSomeMethodCall.Inc

       End Sub
    End Class

In this case the mock class would be injected into what ever class that uses it and when your test code would call the MockFoo.Verify method it would not throw an exception if the number of calls to the "SomeMethod" method matched the value set in the expectation. Now my problem was how to do this in a testable way that was generic and would not require a custom Verify method in every case of the Mock class in the test projects.
The answer was to create a custom ExpectationCounter class.


Public Class ExpectationCounter



    Private _p1 As String



    Sub New(ByVal p1 As String)

        _p1 = p1

        _receivedCalls = 0

    End Sub



    Property Expected As Integer



    Private _receivedCalls As Integer

    Sub Inc()

        _receivedCalls += 1

    End Sub



    Sub Verify()

        If Me.Expected = 0 Then Throw New ExpectationException(String.Format("No expectations set for '{0}'", _p1))

        If _receivedCalls <> Me.Expected Then



            Throw New ExpectationException(String.Format("Expected calls for '{0}' did not occur, Expected {1} got {2}", _p1, Me.Expected, _receivedCalls))



        End If

    End Sub



End Class



and a Mock Class
Imports System.Reflection



<clscompliant(true)>

Public Class Mock



    Public Sub Verify()

        Dim ex() As FieldInfo

        Dim isAnExpectationFieldPresent As Boolean = False

        ex = Me.GetType.GetFields(BindingFlags.NonPublic Or BindingFlags.Instance)

        If ex.Length <= 0 Then Throw New ExpectationException("No expectation fields set")



        For Each expectations As FieldInfo In ex

            If expectations.GetValue(Me).GetType.ToString = "ArdoughterSoftware.MockFramework.ExpectationCounter" Then

                isAnExpectationFieldPresent = True

                CType(expectations.GetValue(Me), ExpectationCounter).Verify()

            End If

        Next

        If Not isAnExpectationFieldPresent Then

            Throw New ExpectationException("No expectation Field set")

        End If

    End Sub



End Class

Now this should let me replace the DotNetMock with my own version and get my existing test to run. I would also expect that they would pass since they did the last time I ran tests on this code. Eventually once I figure out Rhino.Mocks I will replace all the DotNetMock/MyMocks with equivalent tests in that system So then I should be back to my original state but now in VS 2010. Then I can add additional tests to check on performance and then refractor from there.
Since Rhino.Mock is poorly documented in VB.NET I fully intend to post on my learning experiences and perhaps but a full journal of the development of the fantasy calendar project as future blog posts. It will make the project a bit more complicated that the application requirements might merit but in this case the requirements are to learn the mocking framework and the working fantasy calendar is a secondary target.

CiV VII The first 100 hours

First Impressions   I purchased Civ VII from Steam earlier this summer when it was on sale and almost immediately pulled an all-night sessio...