August's Workshop - Duskblade

Discussion in 'General Modification' started by August, Mar 14, 2023.

Remove all ads!
  1. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    Hey @Pygmy any luck on battle sorcerer? I'd like to poke at it. How were you accomplishing the weapon proficiency? I figured a bonus feat might be the way to do it, with the only bonus feat available being Martial Weapon Proficiency.

    Could anyone take a look at this, tell me what my screwup is?

    Code:
    def DSKArcaneAttunementRadial(attachee, args, evt_obj):
        #Check for a charge and the enable flag
        charges = args.get_arg(0)
        if charges < 1:
            return 0
    
        casterLevel = attachee.stat_level_get(classEnum)
    
        # This is the hub for the SLAs.
        attune_parent = tpdp.RadialMenuEntryParent("Arcane Attunement")
        ArcaneAttunementId = attunement_parent.add_child_to_standard(attachee, tpdp.RadialMenuStandardNode.Class)
        
        #detect magic; once this works I'll build for the others
        attune_spell = spell_detect_magic
        attune_detect = tpdp.RadialMenuEntryPythonAction("Detect Magic", D20A_PYTHON_ACTION, DSKAttunementEnum, attune_spell, "TAG_SPELLS_DETECT_MAGIC")
        attune_detect_spelldata = tpdp.D20SpellData(attune_spell)
        attune_detect_spelldata.set_spell_level(casterLevel)
        attune_detect.set_spell_data(attune_detect_spelldata)
        attune_detect.add_as_child(attache, ArcaneAttunementId)
        
        return 0
        
    def DSKArcaneAttunementReset(attachee, args, evt_obj):
        
        # charges are 3 plus int mod
        intScore = obj.stat_level_get(stat_intelligence)
        intModAttunement = ((intScore - 10) / 2) + 3
        args.set_arg(0, intModAttunement)
        
        return 0
        
    def DSKArcaneAttunementCheck(attachee, args, evt_obj):
        #Check for a charge and the enable flag
        charges = args.get_arg(0)
        if charges < 1:
            return 0
        
        currentSequence = tpactions.get_cur_seq()
        spellPacket = currentSequence.spell_packet
        newSpellId = tpactions.get_new_spell_id()
        tpactions.register_spell_cast(spellPacket, newSpellId)
        currentSequence.spell_packet.spell_id = newSpellId
    
        if attachee.anim_goal_throw_spell_w_cast_anim(): # note: the animation goal has internal calls to trigger_spell_effect and the action frame
            new_anim_id = attachee.anim_goal_get_new_id()
            evt_obj.d20a.flags |= D20CAF_NEED_ANIM_COMPLETED
            evt_obj.d20a.anim_id = new_anim_id
            return 0
            
        #Decriment the charges
        charges = charges - 1
        args.set_arg(0, charges)
        return 0
    
    DSKArcaneAttunement = PythonModifier("Arcane Attunement", 0) # arg0 - used this day
    DSKArcaneAttunement.MapToFeat("Duskblade Arcane Attunement")
    DSKArcaneAttunement.AddHook(ET_OnBuildRadialMenuEntry, EK_NONE, DSKArcaneAttunementRadial, ())
    DSKArcaneAttunement.AddHook(ET_OnD20PythonActionCheck, DSKAttunementEnum, DSKArcaneAttunementCheck, ())
    DSKArcaneAttunement.AddHook(ET_OnConditionAdd, EK_NONE, DSKArcaneAttunementReset, ())
    DSKArcaneAttunement.AddHook(ET_OnNewDay, EK_NEWDAY_REST, DSKArcaneAttunementReset, ())
    
     
  2. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    I had to sleep on it to figure out how to best implement the arcane channeling ability mechanically. The rules say the spell discharges after you have made your full attack, so what is happening is the target of the spell is changing to everyone you successfully struck (and spells that keep a charge if you miss stick around, although at l13 this auto-kills charges after the round is over). What should happen is that a modifier is stuck on whoever you hit with your standard action/(l13) whoever you hit with a standard or full attack action. I think I'm going to skip over to implement Duskblade Spell Power first since it will work very similarly.
     
  3. Pygmy

    Pygmy Established Member Supporter

    Joined:
    Oct 8, 2010
    Messages:
    764
    Likes Received:
    82
    Sorry missed this yesterday. Yes copying the fighter bonus feat list and leaving only martial_weapon_proficiency_head is easy enough, I came unstuck when I tried to remove all the even level bonus feats; I eventually concluded that the python code was just calling a background function which created the additional yellow box etc. At the moment the battle sorcerer gets to choose martial weapons at levels 1,2,4 etc...
     
    August likes this.
  4. _doug_

    _doug_ Established Member

    Joined:
    Jul 9, 2009
    Messages:
    318
    Likes Received:
    143
    The duskblade is a fun class. I made an almost complete version of it. I would have finished it but i got stuck on Arcane Channeling. I think everything else worked correctly. Hope you are able to make some progress!
     
    Endarire and August like this.
  5. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    Haha, what the fuck? That's amazing.

    @_doug_ Any chance I can take a look at what you made? I'm still learning a lot but if you finished Spell Power it could help with how I plan to implement Arcane Channeling.

    It's been a minute since I posted my progress, so here. Ghost sound should not be on the spell list and the version that exists is essentially a placeholder, don't use this even "to test"!
     

    Attached Files:

    Last edited: Apr 4, 2023
  6. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    Today I'm mainly taking the day to read and research.
     
    Buffed Rabbit likes this.
  7. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    I spent the day kind of planning how arcane channeling is gonna work, and it's something I've honestly been putting off engaging with. It's what stopped _doug_.

    The ability is really two abilities. In my opinion, it's kind of poorly worded and I doubt it was the intent of designers to make arcane channeling work with non-duskblade spells. Again, it only affects 8 spells, several of which are in Sagenlicht's last beta.

    At level 3, when you cast a spell with a casting time of a standard action, you basically just substitute the touch attack for a melee attack. This is probably best resolved by picking the spell in a menu. By picking the spell, you are unable to make a full attack.

    The obnoxious part is the level 13 version. By picking a spell, you can make a full or standard attack. Standard works as normal, but full tags every single target you hit with an invisible debuff, and after your attacks resolve they are all affected by the spell (chill touch uses only one charge for the full attack, making it the champ).
     
    Buffed Rabbit likes this.
  8. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    Today I've been getting Visual Studio up as well as setting up my own private git, fork of TemplePlus and fork of Sagenlicht's last beta.

    I'll be trying to polish up the help files and prep a push for the NPC classes to be added in, as well as adding an "NPC Classes" flag in the launcher, as my first pull request! After that I'm going to keep poking at the duskblade as well as start taking a look at what Sagenlicht left behind and see what's ready to be committed, especially his back end AOE spell stuff and the duskblade spell list additions.
     
    Sitra Achara and Buffed Rabbit like this.
  9. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    Got a bit lost in the sauce configuring VS/getting builds going. Today's goal is to get that pull request going!
     
    Buffed Rabbit likes this.
  10. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    Recompiled Sagenlicht's last beta for public consumption since the artifact disappeared. It should be treated as a fork of earlier versions - there have been bugfixes in more recent ones.

    Also did a little housekeeping setting up my work environment for future builds, as I might actually wanna climb into the guts of this thing in the future myself!
     
    Last edited: Apr 6, 2023
    Marcelo Abner and Buffed Rabbit like this.
  11. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    Every day's an adventure with this.

    So this was my first pass on the adept, just getting them added to the list of classes it counts up. Clunky, but it works.

    But check out how Obtain Familiar calculates fortitude, reflex, and will saves. It's demented!

    Code:
    def Fortitude( npc ):
    # Returns Fortitude Save Bonus for all the casters class levels
        bonus = 0
        level = npc.stat_level_get(stat_level_barbarian) + npc.stat_level_get(stat_level_cleric) + npc.stat_level_get(stat_level_druid) + npc.stat_level_get(stat_level_fighter) + npc.stat_level_get(stat_level_paladin) + npc.stat_level_get(stat_level_ranger) + npc.stat_level_get(stat_level_monk)
        if ( level != 0 ):
            bonus = ( ( level / 2 ) + 2 )
        level = npc.stat_level_get(stat_level_bard) + npc.stat_level_get(stat_level_rogue) + npc.stat_level_get(stat_level_sorcerer) + npc.stat_level_get(stat_level_wizard)
        if ( level != 0 ):
            bonus = bonus + ( level / 3 )
        return bonus
    
    def Reflex( npc ):
    # Returns Reflex Save Bonus for all the casters class levels
        bonus = 0
        level = npc.stat_level_get(stat_level_barbarian) + npc.stat_level_get(stat_level_cleric) + npc.stat_level_get(stat_level_druid) + npc.stat_level_get(stat_level_fighter) + npc.stat_level_get(stat_level_paladin) + npc.stat_level_get(stat_level_sorcerer) + npc.stat_level_get(stat_level_wizard)
        if ( level != 0 ):
            bonus = ( level / 3 )
        level = npc.stat_level_get(stat_level_ranger) + npc.stat_level_get(stat_level_rogue) + npc.stat_level_get(stat_level_monk) + npc.stat_level_get(stat_level_bard)
        if ( level != 0 ):
            bonus = bonus + ( ( level / 2 ) + 2 )
        return bonus
    
    def Will( npc ):
    # Returns Will Save Bonus for all the casters class levels
        bonus = 0
        level = npc.stat_level_get(stat_level_bard) + npc.stat_level_get(stat_level_cleric) + npc.stat_level_get(stat_level_druid) + npc.stat_level_get(stat_level_monk) + npc.stat_level_get(stat_level_sorcerer) + npc.stat_level_get(stat_level_wizard)
        if ( level != 0 ):
            bonus = ( ( level / 2 ) + 2 )
        level = npc.stat_level_get(stat_level_barbarian) + npc.stat_level_get(stat_level_fighter) + npc.stat_level_get(stat_level_paladin) + npc.stat_level_get(stat_level_ranger) + npc.stat_level_get(stat_level_rogue)
        if ( level != 0 ):
            bonus = bonus + ( level / 3 )
        return bonus
    So, I tried swapping it out for bonus = npc.stat_level_get(stat_save_fortitude/reflexes/willpower) , but that returns the save after modifiers, which is no good. I can see there's been a number of conversations about the Stormlord prerequisites and I think that stat_base_get just doesn't really work right for saves.

    Prior convo with Pygmy reporting it here, got lost in the Sagenlicht beta stuff. Gonna go add it to the issue list.

    This is just like how making arcane attunement made me want to look at ghost sound which made me want to look at Sagenlicht's AOE spell handling stuff which made me want to fix his beta which now makes me want to start raising a fuss about/figuring out how to pythonize the Features page - the OTHER thing standing in the way of getting the friggin' NPC classes working, because picking eight skills to be your skill list is the core feature of the expert class. Everything's a rabbit hole and I'm intimidated as hell because I just poke at this stuff for fun. Honestly considering running screaming to the other project I want to do - model/skin work and making outfits for the bugbears.

    To review, here's what's needed to finish up NPC classes and get them to RAW:
    - For now just bodge Obtain Familiar with gross hacky crap to get saving throws right, gross but necessary; consider stat_base_get for saves in the future
    - Get the Features page pythonized so expert can pick class skills - nothing else will work
    - Make the help files (already started on this).

    Even though I know I'm probably outclassed, I want to at least TRY to attack the "pythonize the features page" problem. I know I'm biting off far more than I can chew even considering it... but it would fix a lot of problems for a lot of classes and really open up a lot of stuff.
     

    Attached Files:

    Last edited: Apr 7, 2023
  12. _doug_

    _doug_ Established Member

    Joined:
    Jul 9, 2009
    Messages:
    318
    Likes Received:
    143
    August likes this.
  13. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    Holy smokes, it's here. I'm dropping everything else and refocusing on finishing the Duskblade! Everything else can wait until this class is feature complete!
     
    Endarire likes this.
  14. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    So I have been a bit busy the last few days but I did compile doug's version to see where it's at. It's far more complete than mine, everything that isn't Arcane Channeling is basically done. Awesome, and great to read and understand what I screwed up with the radials.
    Armored Mage was not working, but I fixed that up easily enough.
    As per RAW, Spell Power ends at the end of combat rather than "in a thousand rounds" but practically nobody cares. Briefly considered a hook to kill it at the end of combat but it's not worth it (and the only thing I could see it mattering towards is knocking out a creature with regeneration like a troll or something and losing Spell Power when it wakes up, which sounds just annoying).

    I see you added routines to check if spells are touch spells in the first place and some condition manipulation stuff that looks very useful.
    Regardless, Arcane Channeling's radial isn't showing up at all, not sure why, gonna poke at that some more today.
     
    Last edited: Apr 10, 2023
    Marcelo Abner and Buffed Rabbit like this.
  15. August

    August Established Member

    Joined:
    Jun 28, 2006
    Messages:
    123
    Likes Received:
    90
    Hmm. Was hoping it'd be just as simple as the d20 actions conflicting with abjurant champion, but no. Changed the d20 action numbers to 2950/51 for compatibility sake but didn't help channeling. Also, the description text so far is scrubbed from dndtools.net and they have telltale formatting bugs (especially apostrophes) so I cleaned up some of the text.

    https://github.com/AugustDrake/TemplePlus/tree/Duskblade :)

    Once Arcane Channeling gets working, I will move into making (or finding betas of and polishing up) every Duskblade spell I can!
     
    Last edited: Apr 11, 2023
Our Host!