Skip to content

Commit

Permalink
Merge pull request #271 from DragonSlayer62/Auto-UnEquipped-casting
Browse files Browse the repository at this point in the history
Added AutoUnequippedCasting Setting in INI
  • Loading branch information
Xoduz committed Apr 27, 2024
2 parents d35267b + 15269a4 commit 526dd08
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 33 deletions.
52 changes: 47 additions & 5 deletions data/js/magic/clumsy.js
Expand Up @@ -106,22 +106,38 @@ function onSpellCast( mSock, mChar, directCast, spellNum )
// The following loop checks to see if any item is currently equipped (if not a GM)
if( mChar.commandlevel < 2 )
{
if( spellType != 2 )
if( spellType != 2 )
{
var itemRHand = mChar.FindItemLayer( 0x01 );
var itemLHand = mChar.FindItemLayer( 0x02 );
if(( itemLHand && itemLHand.type != 119 ) || ( itemRHand && ( itemRHand.type != 9 || itemRHand.type != 119 ))) // Spellbook
var lHandBlocks = false;
var rHandBlocks = false;

// Evaluate blocking for left and right hand items
if( isSpellCastingAllowed( itemRHand ) || isSpellCastingAllowed( itemLHand ))
{
var result = handleItem( itemLHand, itemRHand, mChar );
lHandBlocks = result.lHandBlocks;
rHandBlocks = result.rHandBlocks;
}

if( lHandBlocks || rHandBlocks )
{
if( mSock != null )
{
mSock.SysMessage( GetDictionaryEntry( 708, mSock.language )); // You cannot cast with a weapon equipped.
}
mChar.SetTimer( Timer.SPELLTIME, 0 );
mChar.isCasting = false;
mChar.spellCast = -1;

if( !mChar.isCasting )
{
mChar.SetTimer( Timer.SPELLTIME, 0 );
mChar.isCasting = false;
mChar.spellCast = -1;
}
return true;
}
}
return false;
}

if( mChar.visible == 1 || mChar.visible == 2 )
Expand Down Expand Up @@ -389,4 +405,30 @@ function onSpellSuccess( mSock, mChar, ourTarg )
DoTempEffect( 0, sourceChar, ourTarg, 3, Math.round( mChar.skills.magery / 100 ), 0, 0 );
}

// Function to check if an equipped item allows casting
function isSpellCastingAllowed( item )
{
return item != null && ( item.type == 9 || item.type == 119 ); // Assuming type 9 is spellbook, and type 119 is spell channeling item
}

// Function to handle items
function handleItem( itemLHand, itemRHand, mChar )
{
const UnEquipEnabled = GetServerSetting("AutoUnequippedCasting");
var lHandBlocks = false; // Default to false
var rHandBlocks = false; // Default to false
if( UnEquipEnabled && itemLHand != null && !isSpellCastingAllowed( itemLHand ))
{ // Allow casting if item is spell channeling or type 9 spell book
itemLHand.container = mChar.pack;
lHandBlocks = true; // Set to true if item is blocking
}

if( UnEquipEnabled && itemRHand != null && !isSpellCastingAllowed( itemRHand ))
{ // Allow casting if item is spell channeling or type 9 spell book
itemRHand.container = mChar.pack;
rHandBlocks = true; // Set to true if item is blocking
}
return { lHandBlocks: lHandBlocks, rHandBlocks: rHandBlocks };
}

function _restorecontext_() {}
54 changes: 48 additions & 6 deletions data/js/magic/createfood.js
Expand Up @@ -83,18 +83,34 @@ function onSpellCast( mSock, mChar, directCast, spellNum )
{
var itemRHand = mChar.FindItemLayer( 0x01 );
var itemLHand = mChar.FindItemLayer( 0x02 );
if(( itemLHand && itemLHand.type != 119 ) || ( itemRHand && ( itemRHand.type != 9 || itemRHand.type != 119 ))) // Spellbook
var lHandBlocks = false;
var rHandBlocks = false;

// Evaluate blocking for left and right hand items
if( isSpellCastingAllowed( itemRHand ) || isSpellCastingAllowed( itemLHand ))
{
if( mSock )
var result = handleItem( itemLHand, itemRHand, mChar );
lHandBlocks = result.lHandBlocks;
rHandBlocks = result.rHandBlocks;
}

if( lHandBlocks || rHandBlocks )
{
if( mSock != null )
{
mSock.SysMessage( GetDictionaryEntry( 708, mSock.language )); // You cannot cast with a weapon equipped.
mSock.SysMessage(GetDictionaryEntry( 708, mSock.language )); // You cannot cast with a weapon equipped.
}

if( !mChar.isCasting )
{
mChar.SetTimer( Timer.SPELLTIME, 0 );
mChar.isCasting = false;
mChar.spellCast = -1;
}
mChar.SetTimer( Timer.SPELLTIME, 0 );
mChar.isCasting = false;
mChar.spellCast = -1;
return true;
}
}
return false;
}

// Turn character visible
Expand Down Expand Up @@ -304,4 +320,30 @@ function onSpellSuccess( mSock, mChar, ourTarg )
}
}

// Function to check if an equipped item allows casting
function isSpellCastingAllowed( item )
{
return item != null && ( item.type == 9 || item.type == 119 ); // Assuming type 9 is spellbook, and type 119 is spell channeling item
}

// Function to handle items
function handleItem( itemLHand, itemRHand, mChar )
{
const UnEquipEnabled = GetServerSetting( "AutoUnequippedCasting" );
var lHandBlocks = false; // Default to false
var rHandBlocks = false; // Default to false
if(UnEquipEnabled && itemLHand != null && !isSpellCastingAllowed( itemLHand ))
{ // Allow casting if item is spell channeling or type 9 spell book
itemLHand.container = mChar.pack;
lHandBlocks = true; // Set to true if item is blocking
}

if( UnEquipEnabled && itemRHand != null && !isSpellCastingAllowed( itemRHand ))
{ // Allow casting if item is spell channeling or type 9 spell book
itemRHand.container = mChar.pack;
rHandBlocks = true; // Set to true if item is blocking
}
return { lHandBlocks: lHandBlocks, rHandBlocks: rHandBlocks };
}

function _restorecontext_() {}
53 changes: 47 additions & 6 deletions data/js/magic/level1targ.js
Expand Up @@ -67,20 +67,35 @@ function ItemInHandCheck( mChar, mSock, spellType )
{
var itemRHand = mChar.FindItemLayer( 0x01 );
var itemLHand = mChar.FindItemLayer( 0x02 );
if(( itemLHand && itemLHand.type != 119 ) || ( itemRHand && ( itemRHand.type != 9 || itemRHand.type != 119 ))) // Spellbook
var lHandBlocks = false;
var rHandBlocks = false;

// Evaluate blocking for left and right hand items
if( isSpellCastingAllowed( itemRHand ) || isSpellCastingAllowed( itemLHand ))
{
if( mSock )
var result = handleItem( itemLHand, itemRHand, mChar );
lHandBlocks = result.lHandBlocks;
rHandBlocks = result.rHandBlocks;
}

if( lHandBlocks || rHandBlocks )
{
if( mSock != null )
{
mSock.SysMessage( GetDictionaryEntry( 708, mSock.language )); // You cannot cast with a weapon equipped.
}
mChar.SetTimer( Timer.SPELLTIME, 0 );
mChar.isCasting = false;
mChar.spellCast = -1;

if( !mChar.isCasting )
{
mChar.SetTimer( Timer.SPELLTIME, 0 );
mChar.isCasting = false;
mChar.spellCast = -1;
}
return false;
}
}
return true;
}
return true;
}

function onSpellCast( mSock, mChar, directCast, spellNum )
Expand Down Expand Up @@ -635,4 +650,30 @@ function DispatchSpell( spellNum, mSpell, sourceChar, ourTarg, caster )
}
}

// Function to check if an equipped item allows casting
function isSpellCastingAllowed( item )
{
return item != null && ( item.type == 9 || item.type == 119 ); // Assuming type 9 is spellbook, and type 119 is spell channeling item
}

// Function to handle items
function handleItem( itemLHand, itemRHand, mChar )
{
const UnEquipEnabled = GetServerSetting( "AutoUnequippedCasting" );
var lHandBlocks = false; // Default to false
var rHandBlocks = false; // Default to false
if( UnEquipEnabled && itemLHand != null && !isSpellCastingAllowed( itemLHand ))
{ // Allow casting if item is spell channeling or type 9 spell book
itemLHand.container = mChar.pack;
lHandBlocks = true; // Set to true if item is blocking
}

if( UnEquipEnabled && itemRHand != null && !isSpellCastingAllowed( itemRHand ))
{ // Allow casting if item is spell channeling or type 9 spell book
itemRHand.container = mChar.pack;
rHandBlocks = true; // Set to true if item is blocking
}
return { lHandBlocks: lHandBlocks, rHandBlocks: rHandBlocks };
}

function _restorecontext_() {}
3 changes: 3 additions & 0 deletions source/Changelog.txt
@@ -1,3 +1,6 @@
20/04/2024 - Dragon Slayer/Xuri
Introduced a new INI setting, AutoUnequippedCasting, enhancing customization and control for users.

18/04/2024 - Dragon Slayer
Added Focus Skill to Stam Regain and Mana Regan.

Expand Down
3 changes: 3 additions & 0 deletions source/SEFunctions.cpp
Expand Up @@ -5080,6 +5080,9 @@ JSBool SE_GetServerSetting( JSContext *cx, [[maybe_unused]] JSObject *obj, uintN
case 347: // MOONGATESFACETS
*rval = INT_TO_JSVAL( static_cast<UI32>( cwmWorldState->ServerData()->GetMoongateFacetStatus() ));
break;
case 348: // AUTOUNEQUIPPEDCASTING
*rval = BOOLEAN_TO_JSVAL( cwmWorldState->ServerData()->AutoUnequippedCasting() );
break;
default:
ScriptError( cx, "GetServerSetting: Invalid server setting name provided" );
return false;
Expand Down
23 changes: 22 additions & 1 deletion source/cServerData.cpp
Expand Up @@ -367,7 +367,8 @@ const std::map<std::string, SI32> CServerData::uox3IniCaseValue
{"YOUNGPLAYERSYSTEM"s, 344},
{"YOUNGLOCATION"s, 345},
{"SECRETSHARDKEY"s, 346},
{"MOONGATEFACETS"s, 347}
{"MOONGATEFACETS"s, 347},
{"AUTOUNEQUIPPEDCASTING"s, 348}

};
constexpr auto MAX_TRACKINGTARGETS = 128;
Expand Down Expand Up @@ -478,6 +479,7 @@ constexpr auto BIT_ENABLENPCGUILDDISCOUNTS = UI32( 100 );
constexpr auto BIT_ENABLENPCGUILDPREMIUMS = UI32( 101 );
constexpr auto BIT_SNOOPAWARENESS = UI32( 102 );
constexpr auto BIT_YOUNGPLAYERSYSTEM = UI32( 103 );
constexpr auto BIT_AUTOUNEQUIPPEDCASTING = UI32( 104 );


// New uox3.ini format lookup
Expand Down Expand Up @@ -803,6 +805,7 @@ auto CServerData::ResetDefaults() -> void
TravelSpellsBetweenWorlds( false );
TravelSpellsWhileAggressor( false );
CastSpellsWhileMoving( false );
AutoUnequippedCasting( false );
MaxControlSlots( 0 ); // Default to 0, which is equal to off
MaxFollowers( 5 );
MaxPetOwners( 10 );
Expand Down Expand Up @@ -3868,6 +3871,20 @@ auto CServerData::TravelSpellsWhileAggressor( bool newVal ) -> void
boolVals.set( BIT_TRAVELSPELLSWHILEAGGRESSOR, newVal );
}

//o------------------------------------------------------------------------------------------------o
//| Function - CServerData::AutoUnequippedCasting()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets/Sets whether spells will auto unequipe the hands that is not a spellbook or spellchanneling type.
//o------------------------------------------------------------------------------------------------o
auto CServerData::AutoUnequippedCasting() const -> bool
{
return boolVals.test( BIT_AUTOUNEQUIPPEDCASTING );
}
auto CServerData::AutoUnequippedCasting( bool newVal ) -> void
{
boolVals.set( BIT_AUTOUNEQUIPPEDCASTING, newVal );
}

//o------------------------------------------------------------------------------------------------o
//| Function - CServerData::MaxControlSlots()
//o------------------------------------------------------------------------------------------------o
Expand Down Expand Up @@ -5173,6 +5190,7 @@ auto CServerData::SaveIni( const std::string &filename ) -> bool
ofsOutput << "TRAVELSPELLSWHILEAGGRESSOR=" << ( TravelSpellsWhileAggressor() ? 1 : 0 ) << '\n';
ofsOutput << "HIDESTATSFORUNKNOWNMAGICITEMS=" << HideStatsForUnknownMagicItems() << '\n';
ofsOutput << "CASTSPELLSWHILEMOVING=" << ( CastSpellsWhileMoving() ? 1 : 0 ) << '\n';
ofsOutput << "AUTOUNEQUIPPEDCASTING=" << ( AutoUnequippedCasting() ? 1 : 0 ) << '\n';
ofsOutput << "}" << '\n';

ofsOutput << '\n' << "[start locations]" << '\n' << "{" << '\n';
Expand Down Expand Up @@ -6524,6 +6542,9 @@ auto CServerData::HandleLine( const std::string& tag, const std::string& value )
case 347: // MOONGATEFACETS
SetMoongateFacetStatus( static_cast<UI32>( std::stoul( value, nullptr, 0 )));
break;
case 348: // AUTOUNEQUIPPEDCASTING
AutoUnequippedCasting(( static_cast<UI16>( std::stoul( value, nullptr, 0 )) >= 1 ? true : false ));
break;
default:
rValue = false;
break;
Expand Down
5 changes: 4 additions & 1 deletion source/cServerData.h
Expand Up @@ -212,7 +212,7 @@ class CServerData

// Once over 62, bitsets are costly. std::vector<bool> has a special exception in the c++ specificaiton, to minimize wasted space for bools
// These should be updated
std::bitset<104> boolVals; // Many values stored this way, rather than using bools.
std::bitset<105> boolVals; // Many values stored this way, rather than using bools.
std::bitset<64> spawnRegionsFacets; // Used to determine which facets to enable spawn regions for, set in UOX>INI
std::bitset<64> moongateFacets; // Used to determine which facets to enable moongates for, set in UOX>INI

Expand Down Expand Up @@ -924,6 +924,9 @@ class CServerData
auto TravelSpellsWhileAggressor( bool value ) -> void;
auto TravelSpellsWhileAggressor() const -> bool;

auto AutoUnequippedCasting( bool value ) -> void;
auto AutoUnequippedCasting() const -> bool;

auto ToolUseLimit( bool value ) -> void;
auto ToolUseLimit() const -> bool;

Expand Down
58 changes: 44 additions & 14 deletions source/magic.cpp
Expand Up @@ -4108,20 +4108,50 @@ bool CMagic::SelectSpell( CSocket *mSock, SI32 num )
}

// The following loop checks to see if any item is currently equipped (if not a GM)
if( !mChar->IsGM() )
{
if( type != 2 )
{
CItem *itemRHand = mChar->GetItemAtLayer( IL_RIGHTHAND );
CItem *itemLHand = mChar->GetItemAtLayer( IL_LEFTHAND );
if(( itemLHand != nullptr && itemLHand->GetType() != IT_SPELLCHANNELING ) || ( itemRHand != nullptr && itemRHand->GetType() != IT_SPELLBOOK && itemRHand->GetType() != IT_SPELLCHANNELING ))
{
mSock->SysMessage( 708 ); // You cannot cast with a weapon equipped.
mChar->StopSpell();
return false;
}
}
}
if( !mChar->IsGM() && type != 2 )
{
bool autoUnequipEnabled = cwmWorldState->ServerData()->AutoUnequippedCasting();

CItem *itemRHand = mChar->GetItemAtLayer( IL_RIGHTHAND );
CItem *itemLHand = mChar->GetItemAtLayer( IL_LEFTHAND );
auto mCharPack = mChar->GetPackItem();

// Function to check and possibly unequip an item if it blocks spell casting
auto handleItem = [&]( CItem* item, auto itemCheck, bool& blockFlag )
{
if( item && itemCheck( item ))
{
// If auto-unequip is enabled, make sure pack can hold another item before unequipping
if( autoUnequipEnabled && ValidateObject( mCharPack ) && mCharPack->GetContainsList()->Num() < mCharPack->GetMaxItems() )
{
item->SetCont( mCharPack );
blockFlag = false;
}
else
{
blockFlag = true;
}
}
else
{
blockFlag = false;
}
};

bool lHandBlocks = true;
bool rHandBlocks = true;

// Evaluate blocking for left and right hand items
handleItem( itemLHand, []( CItem* item ) { return item->GetType() != IT_SPELLCHANNELING; }, lHandBlocks );
handleItem( itemRHand, []( CItem* item ) { return item->GetType() != IT_SPELLBOOK && item->GetType() != IT_SPELLCHANNELING; }, rHandBlocks );

if( lHandBlocks || rHandBlocks )
{
mSock->SysMessage( 708 ); // You cannot cast with a weapon equipped.
mChar->StopSpell();
return false;
}
}

if( mChar->GetVisible() == VT_TEMPHIDDEN || mChar->GetVisible() == VT_INVISIBLE )
{
Expand Down

0 comments on commit 526dd08

Please sign in to comment.