PDA

View Full Version : Racial Spells


Charles082986
12-01-2015, 05:24 PM
Is there any way to easily restrict spells by race?

Just restricting the race on the scroll item doesn't prevent a member of the correct class from scribing it into their spellbook.

I have two solutions, illustrated below. I don't like either one, because the first solution requires me to create an extra item and spell, and the other solution doesn't allow the spells to be droppable by NPCs.

For example, creating a "spell" specifically for Iksar Necromancers called "Test Spell 1", I would:

Create a new spell called "Test Spell 1", which deals 5 damage to a single target.
Create a new item called "Spell: Test Spell 1", which is no drop and scribes the spell "Test Spell 1" into your spell book.
Create a new spell called "Summon: Spell: Test Spell 1", which creates the item "Spell: Test Spell 1" on your cursor.
Create an new item called "Test Spell 1 Scroll Case", which is only equipable by IKS NEC, and has 1 charge of "Summon: Spell: Test Spell 1", usable on click if equipped.

Another option is to put NPCs around the world that will hand out an appropriate race/class spell as a result of handing them a specific item or amount of money. In this case, in response to being an IKS NEC who handed "Bob McTestington" 1 gold, the NPC would award you with the "Spell: Test Spell 1" item above.

In my perfect world, the custom racial spell items would just be droppable by NPCs and the scrolls themselves would be tradeable without having to use a equippable clicky item as a gatekeeper to gaining the spell.

Uleat
12-01-2015, 05:52 PM
There are 16 class fields that indicate whether a particular class can use a spell (by level required) or not.

I don't even see a race bitmask in the spells table.


You may be able to add some custom code to the [link]OPMemorizeSpell (https://github.com/EQEmu/Server/blob/master/zone/client_process.cpp#L1118) function that checks for the usable races of the scroll.


EDIT: You'll need to check the item on the cursor to get the race bitmask of the scroll.

This is where a scribed spell scroll is deleted: https://github.com/EQEmu/Server/blob/master/zone/client_process.cpp#L1159

Charles082986
12-01-2015, 07:49 PM
So I could put the race check in either the class/level check section on line 1135 or in the scribing section of the switch statement. I have no clue what coding standards or practices you guys like to follow here. I work as a full stack web developer (though primarily using C# and .NET technologies instead of open source alternatives), so our approaches may be a little different.


case memSpellScribing: { // scribing spell to book
const ItemInst* inst = m_inv[MainCursor];

if(inst && inst->IsType(ItemClassCommon))
{
const Item_Struct* item = inst->GetItem();

if(item && item->Scroll.Effect == (int32)(memspell->spell_id))
{
// new code
bool raceAllowed = false;
uint32 Race_ = GetArrayRace(GetRace());
uint32 Races_ = item->Races;
Race_ = (Race_ == 18 ? 16 : Race_);
for(unsigned int CurrentRace = 1; CurrentRace <= PLAYER_RACE_COUNT; ++CurrentRace){
if(Races_ & 1){
if(Race_ == CurrentRace){
raceAllowed = true;
break;
}
}
Races_ >>= 1;
}
if(!raceAllowed){
Message(0,"Your class/race/deity cannot use this spell.");
break;
}
// end new code
ScribeSpell(memspell->spell_id, memspell->slot);
DeleteItemInInventory(MainCursor, 1, true);
}
else
Message(0,"Scribing spell: inst exists but item does not or spell ids do not match.");
}
else
Message(0,"Scribing a spell without an inst on your cursor?");
break;
}

I opted to put it in the scribing section because there's already a reference to the item on the cursor and it involves a loop, which for performance reasons I'd only like to hit in the event someone is actually scribing a spell instead of every time someone tries to memorize OR scribe a spell.

I pulled the race check from here: https://github.com/EQEmu/Server/blob/master/common/item.cpp#L2356

If there's a simpler or more efficient way of checking the race against the spell scroll race slot, I'm not sure where it would be. Also, this is my first time working with C++, so I made most of my assumptions based on my knowledge of C#. If someone could review it I would be very appreciative.

Uleat
12-01-2015, 08:21 PM
Gimme a few minutes to test out something..if it works, I'll add a rule-based check for that.

(Default will be off..so, you'll need to enable it in the rules table in the database.)

Uleat
12-01-2015, 09:32 PM
Ok, just committed a rule-based check for that. Don't forget to recompile/copy new binaries, update the database, and set the rule to true - in that order.
(If you don't know which rule_set to use, set them all to 'true')


What you will see is the player attempt to scribe the spell, then the server kick out an error message saying that the "item is not usable..."

Being rule-based, and in the main repository, it allows many people access to this feature without having to add it as custom code.

And being defaulted to 'false,' it doesn't change the original server behavior :)


EDIT: For anyone wanting to use this rule, just change to race mask of the item to only those races you wish to use it. The default appears to be 65535 (all races.)

(Don't forget to re-run shared_memory)

Charles082986
12-01-2015, 09:40 PM
Awesome! Thanks!