Aller au contenu

Photo

Custom Spellbooks/lists


  • Veuillez vous connecter pour répondre
19 réponses à ce sujet

#1
Kesaru

Kesaru
  • Members
  • 130 messages
So I'm working on an overhaul of the Spirit Shaman that makes it function more like the Warlock (fewer spells to choose, but they're infinite). I've got all that working fine, but there are a few issues with the Druid spell list used by Spirit Shamans. Some spells are horribly unbalanced when you can use them infinitely (Heal, etc), and the list in general just does not fit the Spirit Shaman as well as it could.
I'd like to make a new spell list unique to the Spirit Shaman composed of certain spells cherry-picked between the Druid/Ranger and Cleric/Paladin lists, but I'm not certain yet what exactly would need to be done for this, and I've read that custom spellbooks are impossible.

So, in regards to them being impossible, does this only apply to entirely new classes or ones that were not originally designated as spellcasters? Is this an issue with what I'm trying with creating a unique spell list for an existing spellcaster?
If it's possible I could probably figure it out on my own, but would anyone have some quick advice on what files I would need to alter and how?

If it really is impossible, or just extremely impractical, I'm sure I could get what I need by altering the Ranger spell list and having them share, especially since Ranger doesn't access any spells past 4.

Modifié par Kesaru, 05 juin 2011 - 05:29 .


#2
MasterChanger

MasterChanger
  • Members
  • 686 messages
Custom spellbooks are really tough for any class. Take a look at spells.2da to understand why.

The values in the BARD, CLERIC, DRUID, etc. columns denote which classes have access to the spell at which levels. In other words, a spellbook is actually defined as a column in spells.2da. Since columns can't be properly added to a 2da, new spellbooks can't be added (though existing ones can be altered).

The only real work-around to this is to use various feats-based systems. Some of Kaedrin's classes that have access to limited spellcasting have sub-radial feats that function as a pseudo-spellbook (this works best with five or fewer spells per level). Alternatively, an entirely new GUI could be created for a class to cast from a feat-based system (like the Tome of Battle).

Messing with feat-based systems is pretty complicated if you want to do it well. Even though you could re-use the same spells scripts and such, thorny issues like caster level, spell resistance, and so on can quickly become problematic.

#3
Kesaru

Kesaru
  • Members
  • 130 messages
I suppose then my best option is to use the Ranger spellbook, but I can't figure out how to change which spellbook the class is assigned to use. Does anyone know which file has that information?
spells.2da, iprp_spells.2da, cls_spkn.2da, cls_spgn.2da, classes.2da, I can't find that information in anything.

Modifié par Kesaru, 05 juin 2011 - 04:42 .


#4
MasterChanger

MasterChanger
  • Members
  • 686 messages
That's a good question, and unfortunately I don't know. It would make sense for it to be classes.2da, but it's not there. Since the spellbook is mapped to a column of spells.2da, rather than a separate 2da entirely (like the spells known and spells gained progressions) it may not be changeable at all.

Another option that I haven't fully fleshed out: maybe you could make an entirely new class (recreating some elements of the Spirit Shaman) and teach it spells through a conversation or GUI? Since you aren't really trying to create a new spellbook, per se, just allow it to use only part of an existing spellbook, maybe that would work better.

There is a SetSpellKnown function that you could use for this.

#5
Kesaru

Kesaru
  • Members
  • 130 messages
I don't have the skills to script it out like that. Worst case scenario, I suppose I could just keep the Druid spell book and remove the more terribly overpowered spells, such as Heal and Harm, and replace them with spells from another class.

#6
MasterChanger

MasterChanger
  • Members
  • 686 messages
Well, I've contemplated what it would take to create a framework for custom spellbooks that goes around the limitations by using some custom 2da's, databases to store known spells, and GUIs to display it all. I've done some work on a custom quickspell menu; a very limited implementation is nearly finished, but I haven't worked on it in a while.

This might also need to use some stuff from Pain's Common/Community Script Library to help calculate spell DC's if one isn't using a "true" spellbook.

It would take a huge amount of work to implement, because you'd need to back-figure information like how many total spells the caster can cast at a certain level, how many they have remaining, etc. There's also the problem that if you use "cheating" to cast a spell it does not use caster level or metamagic correctly. Maybe a group project could address this some day.

Modifié par MasterChanger, 05 juin 2011 - 10:48 .


#7
0100010

0100010
  • Members
  • 87 messages
Custom spell books are possible but with limitation.
In any case, it will require rewriting the entire spells levelup gui.
Rewriting the sppells levelup means: durng on module load: scaning the entire spells.2da and constructing data object for each spell book (by class column) for each spell level and sorting them by spell name.

Once you have this list, you replace the entire SPELLS_AVAILABLE and SPELLS_ADDED listboxs in spells_levelup**.xml with a custom listbox. using your pre-created data object you iteration though those each time the spell level buttun is pressed accorrding to the class and level that was levelup up in. You now have a spells available list that matches what was there. Wire up callback cutton to remove and add listbox rows between spells available and spells added, and save the selections when they click "next". During post levelup use the SetSSpellKnown script command to assign (or remove) all spells that were added to the character that was leveled up.

If you make a new class, that you want to give a spellbook to, you can use this same techniquie to construct your lists and set their spells known. : however consider the following limitations:

IT is not possible to capture gui feedback during character creation. This means no custom levelup page for custom classes. You'll have to not award spells during level 1 or defer it to some sort of post login process.

The only custom spell casting classes that will work are spontaneous caster which have a spells known list and (in classes.2da) does NOT memorize spells, and does NOT have all spells known.
So any sorceror style caster will work. (warlock style will work also, as the state of the infinite flag doesn't matter) The spell known in game gui cannot be edited, This means you cant restrict what spells get added to it as you cannot accurate obtain the row name of the spells in the listbox there due to the way it is handling collapsible buttons. (if it were editable other spllcasting class types could be handled)

That is just to get things working within the existing hotbar and quickcast style casting framework.
Both BM and I have looked into this alot. I am actuall working on a replacement levelup for spell as I described above, as part of my general enhanced levelup overrides.

You will need alot of what CSL does to e able to handle several things correctly.

Create an entirely new casting framework vie new GUI is an entirely new complicated project on its own. Its been discussed, but isn't on the horizon anytime soon.

#8
MasterChanger

MasterChanger
  • Members
  • 686 messages
Interesting, 0100010, modifying what's learned at levelup rather than capturing what's known at any particular time.

However, I think there's an additional limitation that you haven't covered: you can only use this system to restrict a spell-book--in other words to offer a subset of an existing spell-book. I think there'd be problems trying to use it to create some sort of hybrid spell-book. If you teach a wizard-type a cleric spell at level-up, for example, that spell is not going to appear on the Spell-book GUI or the Quickspell GUI.

#9
0100010

0100010
  • Members
  • 87 messages
No, you'd just create a new class column since your skipping the entire hard coding non-sense to begin with. Since you as the builder will know what classes exist you can construct the lists from the 2DAs whether they are new or hybrid or whatever. the other Limitations regarding character creation and it being spontaneous type of caster is still present however.

Try editing your spells.2da and adding a value for wiz_sor column on cure light wounds and see what appears in levelup and in game on the quickcasts etc.I've not done that particular test yet but I suspect it will have a wizard that knows CLWs as whatever level value you put on tWiz_Sor column spell row.

Ive added oddball spells to PC via SetSpellKnown during testing so it works, the key thing to remeber however is that SetSpellKnown respect the limitation set in the Spellsknown column in classes.2da , normally something a wizard doesnt have, which means it has to have column support in spells.2da to work right I suspect.

#10
MasterChanger

MasterChanger
  • Members
  • 686 messages

0100010 wrote...

Try editing your spells.2da and adding a value for wiz_sor column on cure light wounds and see what appears in levelup and in game on the quickcasts etc.I've not done that particular test yet but I suspect it will have a wizard that knows CLWs as whatever level value you put on tWiz_Sor column spell row.


Right, I meant if you wanted to leave one class the same (like the druid in the OP's example) and alter another that uses the same spellbook (like the Spirit Shaman in the OP's ex.). If you don't mind altering the other class, of course you can just alter the column.

Edit: Oh wait, I get it. You'd get it to all the classes that use that spellbook via the column in the 2da, then restrict it from the one you don't want via your method at level-up. Clever! :)

Modifié par MasterChanger, 06 juin 2011 - 02:42 .


#11
0100010

0100010
  • Members
  • 87 messages
There wouldn't be any restricting (in the sense of row removal), your adding spells as rows to a new listbox not taking existing rows away. You only add the ones that that have a column that you have set up.

A more complex explaination w/ psedo code.
In OnModuleLoad:

foreach class in class.2da
{
   if (spellcaster = 1)
   {
      AddToSpellCasterList(classID)
       for (spell_level = 0 spell_level <10 spell_level++)     
          CreateSpellBookObject(classID, spell_level)
    }    
}

foreach spellid in spells.2da
{
    foreach classid in SpellCasterList
   {
      className = GetclassNameFromID(classID)
      spell_level = GetSpellLevelFromSpell2DA(className) 
      //the above can be made to look up the class column even if its a custom column
      if (spell_level > 0)
      {
         spellbook = GetSpellBookObject(classid, spell_level)
         spellinfo = CreateSpellInfoFromSpellRow(spellid)
         AddSpellInfoToSpellBook(spellbook, spellinfo)
      }
   }
}



In OnAdd callback for spells_levelup

classid = GetclassSelectedAtLevelUp()
spell_level = GetDefaultSpellLevelOfNewLevel(classid)
spellbook = GetSpellBookObject(classid, spell_level)
foreach spellinfo in spellbook   //This would really be done via the GetVariableByIndex loop
{
    if (!GetSpellKnown(oPC, spellinfo.id)
        AddListBoxRow(SPELL_LEVELUP, CUSTOM_AVAILABLE_SPELL_LIST, spellinfo.name, .......)
    else
        AddListBoxRow(SPELL_LEVELUP, CUSTOM_ADDED_SPELL_LIST, spellinfo.name, ......)
}

OnLeftClick callback for spell level button on the available listbox
//Same as above, except, pass the spell_level in as a parm of according ot the button pressed

OnLeftClick callback of add spell button on 
//Move the spell from the available list ot the added list using normal gui script functions.
AddSpellToTemporaryAddedList(spellid)

OnLeftClick callback of remove spell button on the added listbox
//Move the spell from the added to the available list using normal gui script functions
AddSpellToTemporaryRemovedList(spellid)

//The reasion we need temporary lists is because the user might click cancel during the levelup process.

OnPostLevelUp

foreach spellid in temporaryAddedSpellList
   SetSpellKnown(oPC, spellid, true)

foreach spellid in temporaryRemovedSpellList
   SetSpellKnown(oPC, spellid, false)

Modifié par 0100010, 06 juin 2011 - 04:28 .


#12
Kesaru

Kesaru
  • Members
  • 130 messages

0100010 wrote...
Try editing your spells.2da and adding a value for wiz_sor column on cure light wounds and see what appears in levelup and in game on the quickcasts etc.I've not done that particular test yet but I suspect it will have a wizard that knows CLWs as whatever level value you put on tWiz_Sor column spell row.

That is how it works. I've given the druid spell book spells like Flesh to Stone, Power Word and Wail of the Banshee already.
Spells don't count as Divine or Arcane as far as I can tell until they're given to a Divine or Arcane class and used by them.
I've successfully altered the levels in which you gain them simply by changing the level number in that column as well, just as you predict.

#13
The Fred

The Fred
  • Members
  • 2 516 messages
0100010, what you're saying is very interesting, and it's similar to what I'm planning on doing to the Cleric in my own module.

My intent is to disable the spell selection screen during character creation (I've tested this and it works, just make the creation spell GUI skip directly to the next GUI) and, as you say, defer it to something which will fire in-game. For level-up, you can do what you want to the screen since the player character object now exists.

I'm doing this so that I can replicate the effects of Domains with custom feats, which can then be controlled based upon deity (i.e. restricting domains to deity) and it's easier because I'm only doing it for Clerics, and I intend to cut Favoured Souls anyway (so I won't have issues with shared spellbooks).

However, it does occur to me that given the work already required, one could extend the same logic to all the other classes, and essentially create whole new spellbooks (though I don't know whether this would allow you to create new spellcasting classes).

#14
0100010

0100010
  • Members
  • 87 messages

The Fred wrote...

I'm doing this so that I can replicate the effects of Domains with custom feats, which can then be controlled based upon deity (i.e. restricting domains to deity) and it's easier because I'm only doing it for Clerics, and I intend to cut Favoured Souls anyway (so I won't have issues with shared spellbooks).

However, it does occur to me that given the work already required, one could extend the same logic to all the other classes, and essentially create whole new spellbooks (though I don't know whether this would allow you to create new spellcasting classes).


Custom spellcasting classes are possible for sorceror/bard/warlock style classes using the above techniques. Other spellcasting class types have a diferent set of problems.


Replacing Domains as you are describing is something that I also aim to get done (replace them all w/ 2 bonus feats awarded at level 2 for clerics (so as to control awardment w/ deity prereqs) and make all domain spells a 1/day spellfeat.  We should talk in IRC to avoid replicating work. There are other thnings (such as feat levelup control) that I have already done or that is in CSL that you will want to use before tackling scripting a system to replace domains.

Modifié par 0100010, 06 juin 2011 - 10:47 .


#15
The Fred

The Fred
  • Members
  • 2 516 messages
I had intended to have the domains work as normal (though gained at L2, or perhaps one a L2, one later, as you say), since as long as the spells are already on the spell list you can add them as you can to a wizard. I've had to jump through some hoops to get it to work, though - Clerics gain all their spells each level, so I'm having to change them to Sorcerer-style casting (as you said above, this is what it ends up at - Wizard-style seems to be hardcoded), give them a large number of allowed learnt spells per level, and then replace the spell selection with custom logic so they only learn the number of spells they should get. This is a pretty big rework and it doesn't seem possible to implement domains in this way without changing the class so much because of the way the engine works.

I've done all this "in theory", testing the pieces I need, but haven't really built anything yet. I do certainly intend to look at the level-up frameworks and stuff as much for the GUI stuff (I've made a bit of GUI in the past but there's so little documentation on it it's like learning to script all over again) as for the rest of it.

I think it should be possible to control all the spontaneous caster classes the same way, but I'm not sure that Cleric and Druid would behave. I hadn't really thought about creating new spellcasting classes, but IIRC a new class gets access to all the "not-really-spell" spells which aren't on any of the other class lists, so if you were hacking the level-up GUI anyway, I suppose you could work things that way, perhaps adding a custom column to the spells.2da or whatever...

#16
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
we definitely should confer in IRC to not reproduce work. Quite a few things are pretty large projects, with different specialists needed, and it's very hard to hash out everything in the forums here.

The CSL solves the issues of caster level, spell power, duration, metamagic and a few other things this requires, basically the spell can be configured as needed from script to do what ever you desire bypassing engine limitations.

I have dataobjects in memory, which can be created for any "spellbook" which allow very fast listing of all the spells for a given level. ie, if you need all the 7th level spells, it has a variable that says the position of the 7th level spells is starting at 244 and has 15 spells, then it can access the object by position to get the id's - basically its an index like a database uses but built into the game. This allows it to throw up the spells of a given level very quickly without hitting a TMI or causing too many issues on the server itself.

I am looking at completely elminating the wizard from directly using the "wizard_sorceror" column, and make all the spells in this column on and activated, so regardless of class they would be on here if any class is using them. Then i am looking at redoing the sorceror and wizard to use my new spell book system entirely. Basically i will not do anything in levelup, it will all be done via spell books what you happen to know. A wizard might be able to learn 3000 spells in their books, but will only see a spell if they find it as loot and will have no idea what spells i offer to players. I will also implement a way to enable them to swap out what is actively known since there is a 254 spell limit on how many you can know, which causes the server to crash if you exceed it. Once i can make it so they have to find a scroll to learn a spell, then i can control what a class knows by what scrolls they get,and limiting which scrolls can be scribed based on class. I hope by only touching the one spell book, it can limit the bugs i create to the 2 classes that use this book, and the new method is actually closer to how PNP is now.

I need to figure out how this will work with sorcerors as well, but one battle at a time. setspellknown and a custom UI i am pretty sue will handle this. ( again copying code i have implemented for learning languages )

Once i get a "free" spell book i can then use that one spellbook to handle any class, i can just "learn" the correct spells for the class as needed via custom gui or the spell books. Basically i can use the engine to do most of what is needed, either by hiding what they should not know, or just dynamically setting them so they know the proper selection of spells. I can really do any class off of the single spell book, even divine ones as the engine really ignores the PNP game mechanics, most of those are done in script.

Once i manage to get all that working, i will be implementing my semi divine caster class the witch doctor, after that is working i should be able to replicate as needed to other classes.

Modifié par painofdungeoneternal, 06 juin 2011 - 11:36 .


#17
0100010

0100010
  • Members
  • 87 messages
I've already tried to force skipping domain granting at level 1 to make it assignable at level 2. What happens instead is the game force assigned as default the top 2 domains when you skip over them, and given that you can't remove domains, this didn't work out how I wanted it to. OOnly option that remained was to not allowed domains as they are set in classes.2da and use domains as bonus feats instead.

#18
The Fred

The Fred
  • Members
  • 2 516 messages
Yeah, I have turned domains off in classes.2da too. The screen skipping works for spell selections, though.

#19
raptor21_c

raptor21_c
  • Members
  • 3 messages
I have managed to add a custom spell list to the spells.2da file; however I am now trying to figure out how to reference the new column in the chargen_spells XML file so that the new spell list shows in the GUI. I suspect that the method, UIListBox_OnUpdate_AvailableSpellList("CHARGEN","SPELL_TEXT","SPELL_IMAGE","SPELL_ACTION"), calls each individual spell in the spell list to the GUI list and I also suspect that the CHARGEN argument controls which spelllist is looked that. Could someone give a little better explanation on how the CHARGEN argument works for pointing to the different spell lists if what I suspect is correct?

Modifié par raptor21_c, 17 juillet 2011 - 04:22 .


#20
Shallina

Shallina
  • Members
  • 1 011 messages
you need to rewrite almost the whole GUI, so you can account the new class.

By doing so, you could even define new 2da files with your new system.

Basically
you rewrite the GUI in order to call only scripted function for all wich is spell or spellbook related and not hard coded function. By doing so
the "limit" for new spell and spellbooks won't be what is hard coded,
but the limit of what you can do with NWNSCRIPT.

This is possible
since the patch 1.23 where OBSIDIAN gave the 4 or 5 core functions
needed to do a CUSTOM GUI that works with scripts and not hard coded
function.

So in order to do custom spellbooks, and so full custom caster class correctly (like the mistyc theurg or your spirit shaman implementation)

You need to do :

1 :) a full scripted version of the character creation process and full scripted GUI for that part.

2:)  A full scripted version of the the character lvl up processand full scripted GUI for that part.  (this has an impact on the "on heartbat" script of any creature that can lvl up where you need to check if the object is lvling up or no, and launching or updating the custom GUI with the information you fetched, this is just an exemple, there are many more impact).

3:) And a full in game scripted GUI for the element involved (character panel, spellbook gui and probably more).


By doing a full custom GUI it's probably possible to raise the lvl cap propelly as much as you wants as well since you'll fetch the information in new 2Da you'll have made yourself, and more importantly you'll be able to do what you want with those information.

Basically the first thing to do if you want to do something that goes beyond what is hard coded in the GUI, is a custom scripted GUI. Wich was nevers made up until now.

That GUI could be made by using the existing look and presentation, it's possible to use the current XML GUI file, and tweak them so they''ll receive scripted parameter instead of hard coded one, and that they'll call scripted function instead of hard coded one.

It's possible, it's not easy, and it's a really big work.

The one who will do it, (tweak the current UI so it won't call hard coded function, but scripted fucntion) will probably be a "community heroes" especially for all the poeple who wants "custom spellbooks", and those who wants to raise the lvl cap.

Modifié par Shallina, 18 juillet 2011 - 09:15 .