From 363ce296c459a21253c67b783fe85e2ef91c2786 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:38:03 -0500 Subject: [PATCH 1/7] Hit/Defense Chance Properties --- source/CPacketSend.cpp | 14 ++++++++ source/UOXJSPropertyEnums.h | 2 ++ source/UOXJSPropertyFuncs.cpp | 4 +++ source/UOXJSPropertySpecs.h | 2 ++ source/cBaseObject.cpp | 62 +++++++++++++++++++++++++++++++++++ source/cBaseObject.h | 11 +++++++ source/cChar.cpp | 7 ++++ source/cItem.cpp | 14 ++++++++ source/combat.cpp | 6 ++-- source/items.cpp | 2 ++ source/ssection.cpp | 4 +++ source/ssection.h | 2 ++ 12 files changed, 127 insertions(+), 3 deletions(-) diff --git a/source/CPacketSend.cpp b/source/CPacketSend.cpp index e1d8ee4ca..04d145b29 100644 --- a/source/CPacketSend.cpp +++ b/source/CPacketSend.cpp @@ -7657,6 +7657,20 @@ void CPToolTip::CopyItemData( CItem& cItem, size_t &totalStringLen, bool addAmou FinalizeData( tempEntry, totalStringLen ); } + if( cItem.GetHitChance() > 0 ) + { + tempEntry.stringNum = 1060415; // hit chance increase ~1_val~% + tempEntry.ourText = oldstrutil::number( cItem.GetHitChance() ); + FinalizeData( tempEntry, totalStringLen ); + } + + if( cItem.GetDefenseChance() > 0 ) + { + tempEntry.stringNum = 1060408; // defense chance increase ~1_val~% + tempEntry.ourText = oldstrutil::number( cItem.GetDefenseChance() ); + FinalizeData( tempEntry, totalStringLen ); + } + if( cItem.GetStrength() > 1 ) { tempEntry.stringNum = 1061170; // strength requirement ~1_val~ diff --git a/source/UOXJSPropertyEnums.h b/source/UOXJSPropertyEnums.h index af309d496..f471df16e 100644 --- a/source/UOXJSPropertyEnums.h +++ b/source/UOXJSPropertyEnums.h @@ -461,6 +461,8 @@ enum CI_Properties CIP_DAMAGEPOISON, CIP_DAMAGERAIN, CIP_DAMAGESNOW, + CIP_HITCHANCE, + CIP_DEFENSECHANCE, CIP_NAME2, CIP_ISITEM, CIP_ISCHAR, diff --git a/source/UOXJSPropertyFuncs.cpp b/source/UOXJSPropertyFuncs.cpp index 3823356f9..02ff0cbb2 100644 --- a/source/UOXJSPropertyFuncs.cpp +++ b/source/UOXJSPropertyFuncs.cpp @@ -676,6 +676,8 @@ JSBool CItemProps_getProperty( JSContext *cx, JSObject *obj, jsval id, jsval *vp case CIP_DAMAGERAIN: *vp = BOOLEAN_TO_JSVAL( gPriv->GetWeatherDamage( RAIN )); break; case CIP_DAMAGESNOW: *vp = BOOLEAN_TO_JSVAL( gPriv->GetWeatherDamage( SNOW )); break; case CIP_SPEED: *vp = INT_TO_JSVAL( gPriv->GetSpeed() ); break; + case CIP_HITCHANCE: *vp = INT_TO_JSVAL( gPriv->GetHitChance() ); break; + case CIP_DEFENSECHANCE: *vp = INT_TO_JSVAL( gPriv->GetDefenseChance() ); break; case CIP_NAME2: tString = JS_NewStringCopyZ( cx, gPriv->GetName2().c_str() ); *vp = STRING_TO_JSVAL( tString ); @@ -1321,6 +1323,8 @@ JSBool CItemProps_setProperty( JSContext *cx, JSObject *obj, jsval id, jsval *vp case CIP_DAMAGERAIN: gPriv->SetWeatherDamage( RAIN, encaps.toBool() ); break; case CIP_DAMAGESNOW: gPriv->SetWeatherDamage( SNOW, encaps.toBool() ); break; case CIP_SPEED: gPriv->SetSpeed( static_cast( encaps.toInt() )); break; + case CIP_HITCHANCE: gPriv->SetHitChance( static_cast( encaps.toInt() )); break; + case CIP_DEFENSECHANCE: gPriv->SetDefenseChance( static_cast( encaps.toInt() )); break; case CIP_NAME2: gPriv->SetName2( encaps.toString() ); break; case CIP_RACE: gPriv->SetRace( static_cast( encaps.toInt() )); break; case CIP_MAXHP: gPriv->SetMaxHP( static_cast( encaps.toInt() )); break; diff --git a/source/UOXJSPropertySpecs.h b/source/UOXJSPropertySpecs.h index 3149dc0ec..b77c023aa 100644 --- a/source/UOXJSPropertySpecs.h +++ b/source/UOXJSPropertySpecs.h @@ -535,6 +535,8 @@ inline JSPropertySpec CItemProps[] = { "ammoFXHue", CIP_AMMOFXHUE, JSPROP_ENUMANDPERM, nullptr, nullptr }, { "ammoFXRender", CIP_AMMOFXRENDER, JSPROP_ENUMANDPERM, nullptr, nullptr }, { "speed", CIP_SPEED, JSPROP_ENUMANDPERM, nullptr, nullptr }, + { "hitChance", CIP_HITCHANCE, JSPROP_ENUMANDPERM, nullptr, nullptr }, + { "defenseChance", CIP_DEFENSECHANCE, JSPROP_ENUMANDPERM, nullptr, nullptr }, { "multi", CIP_MULTI, JSPROP_ENUMANDPERM, nullptr, nullptr }, { "maxRange", CIP_MAXRANGE, JSPROP_ENUMANDPERM, nullptr, nullptr }, { "baseRange", CIP_BASERANGE, JSPROP_ENUMANDPERM, nullptr, nullptr }, diff --git a/source/cBaseObject.cpp b/source/cBaseObject.cpp index 506c247ac..bfb143b5d 100644 --- a/source/cBaseObject.cpp +++ b/source/cBaseObject.cpp @@ -1036,6 +1036,48 @@ void CBaseObject::IncHP( SI16 amtToChange ) SetHP( hitpoints + amtToChange ); } +//o------------------------------------------------------------------------------------------------o +//| Function - CBaseObject::GetHitChance() +//| CBaseObject::SetHitChance() +//| Date - 14 June, 2024 +//o------------------------------------------------------------------------------------------------o +//| Purpose - Gets/Sets the Defense Chance of the Item Equiped +//o------------------------------------------------------------------------------------------------o +SI16 CBaseObject::GetHitChance( void ) const +{ + return hitChance; +} +void CBaseObject::SetHitChance( SI16 newValue ) +{ + hitChance = newValue; + + if( CanBeObjType( OT_ITEM )) + { + ( static_cast( this ))->UpdateRegion(); + } +} + +//o------------------------------------------------------------------------------------------------o +//| Function - CBaseObject::GetDefenseChance() +//| CBaseObject::SetDefenseChance() +//| Date - 14 June, 2024 +//o------------------------------------------------------------------------------------------------o +//| Purpose - Gets/Sets the Defense Chance of the Item Equiped +//o------------------------------------------------------------------------------------------------o +SI16 CBaseObject::GetDefenseChance( void ) const +{ + return defenseChance; +} +void CBaseObject::SetDefenseChance( SI16 newValue ) +{ + defenseChance = newValue; + + if( CanBeObjType( OT_ITEM )) + { + ( static_cast( this ))->UpdateRegion(); + } +} + //o------------------------------------------------------------------------------------------------o //| Function - CBaseObject::GetDir() //| CBaseObject::SetDir() @@ -1661,6 +1703,26 @@ void CBaseObject::IncIntelligence( SI16 toInc ) SetIntelligence( intelligence + toInc ); } +//o------------------------------------------------------------------------------------------------o +//| Function - CBaseObject::IncHitChance() +//o------------------------------------------------------------------------------------------------o +//| Purpose - Increments the object's Hit Chance value +//o------------------------------------------------------------------------------------------------o +void CBaseObject::IncHitChance( SI16 toInc ) +{ + SetHitChance( hitChance + toInc ); +} + +//o------------------------------------------------------------------------------------------------o +//| Function - CBaseObject::IncDefenseChance() +//o------------------------------------------------------------------------------------------------o +//| Purpose - Increments the object's Hit Chance value +//o------------------------------------------------------------------------------------------------o +void CBaseObject::IncDefenseChance( SI16 toInc ) +{ + SetDefenseChance( defenseChance + toInc ); +} + //o------------------------------------------------------------------------------------------------o //| Function - CBaseObject::DumpFooter() //o------------------------------------------------------------------------------------------------o diff --git a/source/cBaseObject.h b/source/cBaseObject.h index 638e826f7..4b5c66329 100644 --- a/source/cBaseObject.h +++ b/source/cBaseObject.h @@ -69,6 +69,8 @@ class CBaseObject SI16 dexterity; SI16 intelligence; SI16 hitpoints; + SI16 hitChance; + SI16 defenseChance; VisibleTypes visible; SI16 hiDamage; SI16 loDamage; @@ -223,6 +225,12 @@ class CBaseObject virtual void SetHP( SI16 newValue ); void IncHP( SI16 amtToChange ); + virtual SI16 GetHitChance( void ) const; + virtual void SetHitChance( SI16 newValue ); + + virtual SI16 GetDefenseChance( void ) const; + virtual void SetDefenseChance( SI16 newValue ); + void SetDir( UI08 newDir, bool sendUpdate = true ); UI08 GetDir( void ) const; @@ -256,6 +264,9 @@ class CBaseObject void IncDexterity( SI16 toInc = 1 ); void IncIntelligence( SI16 toInc = 1 ); + void IncHitChance( SI16 toInc = 1 ); + void IncDefenseChance( SI16 toInc = 1 ); + virtual void PostLoadProcessing( void ); virtual bool LoadRemnants( void ) = 0; diff --git a/source/cChar.cpp b/source/cChar.cpp index 7aa03f6fa..6bb36cb56 100644 --- a/source/cChar.cpp +++ b/source/cChar.cpp @@ -2920,6 +2920,9 @@ bool CChar::WearItem( CItem *toWear ) IncDexterity2( itemLayers[tLayer]->GetDexterity2() ); IncIntelligence2( itemLayers[tLayer]->GetIntelligence2() ); + IncHitChance( itemLayers[tLayer]->GetHitChance() ); + IncDefenseChance( itemLayers[tLayer]->GetDefenseChance() ); + if( toWear->IsPostLoaded() ) { if( itemLayers[tLayer]->GetPoisoned() ) @@ -2979,6 +2982,10 @@ bool CChar::TakeOffItem( ItemLayers Layer ) IncStrength2( -itemLayers[Layer]->GetStrength2() ); IncDexterity2( -itemLayers[Layer]->GetDexterity2() ); IncIntelligence2( -itemLayers[Layer]->GetIntelligence2() ); + + IncHitChance( -itemLayers[Layer]->GetHitChance() ); + IncDefenseChance( -itemLayers[Layer]->GetDefenseChance() ); + if( itemLayers[Layer]->GetPoisoned() ) { if( itemLayers[Layer]->GetPoisoned() > GetPoisoned() ) diff --git a/source/cItem.cpp b/source/cItem.cpp index 3c6523d5d..5843cfb86 100644 --- a/source/cItem.cpp +++ b/source/cItem.cpp @@ -1638,6 +1638,8 @@ auto CItem::CopyData( CItem *target ) -> void target->SetRndValueRate( GetRndValueRate() ); target->SetSpawn( GetSpawn() ); target->SetSpeed( GetSpeed() ); + target->SetHitChance( GetHitChance() ); + target->SetDefenseChance( GetDefenseChance() ); target->SetSpell( 0, GetSpell( 0 )); target->SetSpell( 1, GetSpell( 1 )); target->SetSpell( 2, GetSpell( 2 )); @@ -1736,6 +1738,8 @@ bool CItem::DumpBody( std::ostream &outStream ) const outStream << "BaseWeight=" + std::to_string( GetBaseWeight() ) + newLine; outStream << "MaxItems=" + std::to_string( GetMaxItems() ) + newLine; outStream << "MaxHP=" + std::to_string( GetMaxHP() ) + newLine; + outStream << "HitChance=" + std::to_string( GetHitChance() ) + newLine; + outStream << "DefenseChance=" + std::to_string( GetDefenseChance() ) + newLine; outStream << "Speed=" + std::to_string( GetSpeed() ) + newLine; outStream << "Movable=" + std::to_string( GetMovable() ) + newLine; outStream << "Priv=" + std::to_string( GetPriv() ) + newLine; @@ -1859,6 +1863,11 @@ bool CItem::HandleLine( std::string &UTag, std::string &data ) SetDye( static_cast( std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 )) == 1 ); rValue = true; } + else if( UTag == "DEFENSECHANCE" ) + { + SetDefenseChance( static_cast( std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 ))); + rValue = true; + } break; case 'E': if( UTag == "ENTRYMADEFROM" ) @@ -1905,6 +1914,11 @@ bool CItem::HandleLine( std::string &UTag, std::string &data ) SetWeatherDamage( HEAT, static_cast( std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 )) == 1 ); rValue = true; } + else if( UTag == "HITCHANCE" ) + { + SetHitChance( static_cast( std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 ))); + rValue = true; + } break; case 'L': if( UTag == "LAYER" ) diff --git a/source/combat.cpp b/source/combat.cpp index 8817d7b3d..066e3e80e 100644 --- a/source/combat.cpp +++ b/source/combat.cpp @@ -2883,9 +2883,9 @@ bool CHandleCombat::HandleCombat( CSocket *mSock, CChar& mChar, CChar *ourTarg ) maxAttHitChanceBonus = 50; } - // Fetch bonuses to hitChance/defenseChance from AoS item properties, when implemented - //attHitChanceBonus = GetAttackerHitChanceBonus(); - //defDefenseChanceBonus = GetDefenderDefenseChanceBonus(); + // Fetch bonuses to hitChance/defenseChance from AoS item properties + attHitChanceBonus = mChar.GetHitChance(); + defDefenseChanceBonus = mChar.GetDefenseChance(); R32 attackerHitChance = ( static_cast( attackSkill / 10 ) + 20 ) * ( 100 + std::min( attHitChanceBonus, static_cast( maxAttHitChanceBonus ))); R32 defenderDefenseChance = ( static_cast( defendSkill / 10 ) + 20 ) * ( 100 + std::min( defDefenseChanceBonus, static_cast( 45 ))); diff --git a/source/items.cpp b/source/items.cpp index 1cd4a2aaf..5c4726c11 100644 --- a/source/items.cpp +++ b/source/items.cpp @@ -229,6 +229,7 @@ auto ApplyItemSection( CItem *applyTo, CScriptSection *toApply, std::string sect case DFNTAG_DISPELLABLE: applyTo->SetDispellable( true ); break; case DFNTAG_DISABLED: applyTo->SetDisabled( ndata != 0 ); break; case DFNTAG_DOORFLAG: break; + case DFNTAG_DEFENSECHANCE: applyTo->SetDefenseChance( static_cast( ndata )); break; case DFNTAG_GOOD: applyTo->SetGood( static_cast( ndata )); break; case DFNTAG_GLOW: applyTo->SetGlow( ndata ); break; case DFNTAG_GLOWBC: applyTo->SetGlowColour( static_cast( ndata )); break; @@ -338,6 +339,7 @@ auto ApplyItemSection( CItem *applyTo, CScriptSection *toApply, std::string sect } break; case DFNTAG_HIDAMAGE: applyTo->SetHiDamage( static_cast( ndata )); break; + case DFNTAG_HITCHANCE: applyTo->SetHitChance( static_cast( ndata )); break; case DFNTAG_HEAT: applyTo->SetWeatherDamage( HEAT, ndata != 0 ); break; case DFNTAG_ID: // applyTo->SetId( static_cast( ndata )); break; if( ssecs.size() == 1 ) diff --git a/source/ssection.cpp b/source/ssection.cpp index c2a563b47..73bb2e94b 100644 --- a/source/ssection.cpp +++ b/source/ssection.cpp @@ -66,6 +66,7 @@ const UI08 dfnDataTypes[DFNTAG_COUNTOFTAGS] = DFN_NUMERIC, // DFNTAG_DOORFLAG, DFN_NUMERIC, // DFNTAG_DYE, DFN_NUMERIC, // DFNTAG_DYEBEARD, + DFN_NUMERIC, // DFNTAG_DEFENSECHANCE, DFN_NUMERIC, // DFNTAG_DYEHAIR, DFN_STRING, // DFNTAG_ELEMENTRESIST, DFN_STRING, // DFNTAG_ERBONUS, @@ -111,6 +112,7 @@ const UI08 dfnDataTypes[DFNTAG_COUNTOFTAGS] = DFN_NUMERIC, // DFNTAG_HEAT, DFN_DOUBLENUMERIC, // DFNTAG_HERDING, DFN_NUMERIC, // DFNTAG_HIDAMAGE, + DFN_NUMERIC, // DFNTAG_HITCHANCE, DFN_DOUBLENUMERIC, // DFNTAG_HIDING, DFN_NODATA, // DFNTAG_HIRELING, DFN_DOUBLENUMERIC, // DFNTAG_HP, @@ -321,6 +323,7 @@ const std::map strToDFNTag {"DYEABLE"s, DFNTAG_DYE}, {"DYEHAIR"s, DFNTAG_DYEHAIR}, {"DYEBEARD"s, DFNTAG_DYEBEARD}, + {"DEFENSECHANCE"s, DFNTAG_DEFENSECHANCE}, {"ELEMENTRESIST"s, DFNTAG_ELEMENTRESIST}, {"ERBONUS"s, DFNTAG_ERBONUS}, {"EMOTECOLOR"s, DFNTAG_EMOTECOLOUR}, @@ -366,6 +369,7 @@ const std::map strToDFNTag {"HEAT"s, DFNTAG_HEAT}, {"HERDING"s, DFNTAG_HERDING}, {"HIDAMAGE"s, DFNTAG_HIDAMAGE}, + {"HITCHANCE"s, DFNTAG_HITCHANCE}, {"HIDING"s, DFNTAG_HIDING}, {"HIRELING"s, DFNTAG_HIRELING}, {"HP"s, DFNTAG_HP}, diff --git a/source/ssection.h b/source/ssection.h index a2a660aec..beaa359ab 100644 --- a/source/ssection.h +++ b/source/ssection.h @@ -71,6 +71,7 @@ enum DFNTAGS DFNTAG_DISPELLABLE, DFNTAG_DISABLED, DFNTAG_DOORFLAG, + DFNTAG_DEFENSECHANCE, DFNTAG_DYE, DFNTAG_DYEBEARD, DFNTAG_DYEHAIR, @@ -118,6 +119,7 @@ enum DFNTAGS DFNTAG_HEAT, DFNTAG_HERDING, DFNTAG_HIDAMAGE, + DFNTAG_HITCHANCE, DFNTAG_HIDING, DFNTAG_HIRELING, DFNTAG_HP, From 8863f5de2726fbc5e34a1e56f229063a0935c1d1 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:42:36 -0500 Subject: [PATCH 2/7] Changelog --- source/Changelog.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/Changelog.txt b/source/Changelog.txt index f64afbc32..348b45e14 100644 --- a/source/Changelog.txt +++ b/source/Changelog.txt @@ -1,3 +1,9 @@ +14/06/2024 - Dragon Slayer + Added two new DFN tags for Items: + HITCHANCE=# // Increases the player's chance to hit a target with wrestling, melee and ranged weapons. + DEFENSECHANCE=# // Increases the wearer's chance that his opponents' swings (or arrows/bolts) will miss. + These are also available as JS Engine object properties: .hitChance, .defenseChance + 1/05/2024 - Dragon Slayer/Xuri Fixed AutoUnequipAttempt function in clumsy.js, createfood.js level1target.js, will no longer fail on casting and return to hardcode. Fixed createfood to check for reagents on cast. From b63ceaeeb6445e113199dc61d4bbb7367f1fb576 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Sun, 16 Jun 2024 02:04:48 -0500 Subject: [PATCH 3/7] Update cBaseObject.cpp --- source/cBaseObject.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/cBaseObject.cpp b/source/cBaseObject.cpp index bfb143b5d..b0e7a538f 100644 --- a/source/cBaseObject.cpp +++ b/source/cBaseObject.cpp @@ -1039,7 +1039,6 @@ void CBaseObject::IncHP( SI16 amtToChange ) //o------------------------------------------------------------------------------------------------o //| Function - CBaseObject::GetHitChance() //| CBaseObject::SetHitChance() -//| Date - 14 June, 2024 //o------------------------------------------------------------------------------------------------o //| Purpose - Gets/Sets the Defense Chance of the Item Equiped //o------------------------------------------------------------------------------------------------o @@ -1060,7 +1059,6 @@ void CBaseObject::SetHitChance( SI16 newValue ) //o------------------------------------------------------------------------------------------------o //| Function - CBaseObject::GetDefenseChance() //| CBaseObject::SetDefenseChance() -//| Date - 14 June, 2024 //o------------------------------------------------------------------------------------------------o //| Purpose - Gets/Sets the Defense Chance of the Item Equiped //o------------------------------------------------------------------------------------------------o From f6989ca218146962e9cef0f932fffd0e1d13cd3c Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Sun, 16 Jun 2024 02:48:12 -0500 Subject: [PATCH 4/7] Update cBaseObject.cpp --- source/cBaseObject.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/cBaseObject.cpp b/source/cBaseObject.cpp index b0e7a538f..9eedebfff 100644 --- a/source/cBaseObject.cpp +++ b/source/cBaseObject.cpp @@ -94,6 +94,8 @@ const SI16 DEFBASE_KILLS = 0; const UI16 DEFBASE_RESIST = 0; const bool DEFBASE_NAMEREQUESTACTIVE = 0; const ExpansionRuleset DEFBASE_ORIGIN = ER_UO; +const SI16 DEFBASE_HITCHANCE = 0; +const SI16 DEFBASE_DEFENSECHANCE = 0; //o------------------------------------------------------------------------------------------------o //| Function - CBaseObject constructor @@ -110,7 +112,8 @@ loDamage( DEFBASE_LODAMAGE ), weight( DEFBASE_WEIGHT ), mana( DEFBASE_MANA ), stamina( DEFBASE_STAMINA ), scriptTrig( DEFBASE_SCPTRIG ), st2( DEFBASE_STR2 ), dx2( DEFBASE_DEX2 ), in2( DEFBASE_INT2 ), FilePosition( DEFBASE_FP ), poisoned( DEFBASE_POISONED ), carve( DEFBASE_CARVE ), oldLocX( 0 ), oldLocY( 0 ), oldLocZ( 0 ), oldTargLocX( 0 ), oldTargLocY( 0 ), -fame( DEFBASE_FAME ), karma( DEFBASE_KARMA ), kills( DEFBASE_KILLS ), subRegion( DEFBASE_SUBREGION ), nameRequestActive( DEFBASE_NAMEREQUESTACTIVE ), origin( DEFBASE_ORIGIN ) +fame( DEFBASE_FAME ), karma( DEFBASE_KARMA ), kills( DEFBASE_KILLS ), subRegion( DEFBASE_SUBREGION ), nameRequestActive( DEFBASE_NAMEREQUESTACTIVE ), origin( DEFBASE_ORIGIN ), +hitChance( DEFBASE_HITCHANCE ), defenseChance( DEFBASE_DEFENSECHANCE ) { multis = nullptr; tempMulti = INVALIDSERIAL; From cd35741ff276118143e46d1f023851059bc20a36 Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 14 Jan 2025 21:44:16 -0600 Subject: [PATCH 5/7] Update Updated so they work directly on chars for the DCI and HCI just like retail AOS --- source/UOXJSPropertyEnums.h | 2 ++ source/UOXJSPropertyFuncs.cpp | 4 ++++ source/UOXJSPropertySpecs.h | 2 ++ source/cChar.cpp | 16 +++++++++++++++- 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/source/UOXJSPropertyEnums.h b/source/UOXJSPropertyEnums.h index f471df16e..a99bd3628 100644 --- a/source/UOXJSPropertyEnums.h +++ b/source/UOXJSPropertyEnums.h @@ -339,6 +339,8 @@ enum CC_Properties CCP_SPAWNSERIAL, CCP_SPATTACK, CCP_SPDELAY, + CCP_HITCHANCE, + CCP_DEFENSECHANCE, CCP_AITYPE, CCP_SPLIT, CCP_SPLITCHANCE, diff --git a/source/UOXJSPropertyFuncs.cpp b/source/UOXJSPropertyFuncs.cpp index 02ff0cbb2..ef170971c 100644 --- a/source/UOXJSPropertyFuncs.cpp +++ b/source/UOXJSPropertyFuncs.cpp @@ -1998,6 +1998,8 @@ JSBool CCharacterProps_getProperty( JSContext *cx, JSObject *obj, jsval id, jsva case CCP_HOUSEICONS: *vp = BOOLEAN_TO_JSVAL( gPriv->ViewHouseAsIcon() ); break; case CCP_SPATTACK: *vp = INT_TO_JSVAL( gPriv->GetSpAttack() ); break; case CCP_SPDELAY: *vp = INT_TO_JSVAL( gPriv->GetSpDelay() ); break; + case CCP_HITCHANCE: *vp = INT_TO_JSVAL( gPriv->GetHitChance() ); break; + case CCP_DEFENSECHANCE: *vp = INT_TO_JSVAL( gPriv->GetDefenseChance() ); break; case CCP_AITYPE: *vp = INT_TO_JSVAL( gPriv->GetNpcAiType() ); break; case CCP_SPLIT: *vp = INT_TO_JSVAL( gPriv->GetSplit() ); break; case CCP_SPLITCHANCE: *vp = INT_TO_JSVAL( gPriv->GetSplitChance() ); break; @@ -2503,6 +2505,8 @@ JSBool CCharacterProps_setProperty( JSContext *cx, JSObject *obj, jsval id, jsva case CCP_HOUSEICONS: gPriv->SetViewHouseAsIcon( encaps.toBool() ); break; case CCP_SPATTACK: gPriv->SetSpAttack( static_cast( encaps.toInt() )); break; case CCP_SPDELAY: gPriv->SetSpDelay( static_cast( encaps.toInt() )); break; + case CCP_HITCHANCE: gPriv->SetHitChance( static_cast( encaps.toInt() )); break; + case CCP_DEFENSECHANCE: gPriv->SetDefenseChance( static_cast( encaps.toInt() )); break; case CCP_AITYPE: gPriv->SetNPCAiType( static_cast( encaps.toInt() )); break; case CCP_SPLIT: gPriv->SetSplit( static_cast( encaps.toInt() )); break; case CCP_SPLITCHANCE: gPriv->SetSplitChance( static_cast( encaps.toInt() ));break; diff --git a/source/UOXJSPropertySpecs.h b/source/UOXJSPropertySpecs.h index b77c023aa..1585d151a 100644 --- a/source/UOXJSPropertySpecs.h +++ b/source/UOXJSPropertySpecs.h @@ -357,6 +357,8 @@ inline JSPropertySpec CCharacterProps[] = { "houseicons", CCP_HOUSEICONS, JSPROP_ENUMANDPERM, nullptr, nullptr }, { "spattack", CCP_SPATTACK, JSPROP_ENUMANDPERM, nullptr, nullptr }, { "spdelay", CCP_SPDELAY, JSPROP_ENUMANDPERM, nullptr, nullptr }, + { "hitChance", CCP_HITCHANCE, JSPROP_ENUMANDPERM, nullptr, nullptr }, + { "defenseChance", CCP_DEFENSECHANCE, JSPROP_ENUMANDPERM, nullptr, nullptr }, { "aitype", CCP_AITYPE, JSPROP_ENUMANDPERM, nullptr, nullptr }, { "split", CCP_SPLIT, JSPROP_ENUMANDPERM, nullptr, nullptr }, { "splitchance", CCP_SPLITCHANCE, JSPROP_ENUMANDPERM, nullptr, nullptr }, diff --git a/source/cChar.cpp b/source/cChar.cpp index 6bb36cb56..eb70922f6 100644 --- a/source/cChar.cpp +++ b/source/cChar.cpp @@ -2411,6 +2411,8 @@ void CChar::CopyData( CChar *target ) target->SetNextAct( nextAct ); target->SetSquelched( GetSquelched() ); target->SetMeditating( IsMeditating() ); + target->SetHitChance( GetHitChance() ); + target->SetDefenseChance( GetDefenseChance() ); target->SetStealth( stealth ); target->SetRunning( running ); target->SetRace( GetRace() ); @@ -3141,6 +3143,8 @@ bool CChar::DumpBody( std::ostream &outStream ) const //------------------------------------------------------------------------------------------- outStream << "CanRun=" + std::to_string((( CanRun() && IsNpc() ) ? 1 : 0 )) + newLine; outStream << "CanAttack=" + std::to_string(( GetCanAttack() ? 1 : 0 )) + newLine; + outStream << "HitChance=" + std::to_string( GetHitChance() ) + newLine; + outStream << "DefChance=" + std::to_string( GetDefenseChance() ) + newLine; outStream << "AllMove=" + std::to_string(( AllMove() ? 1 : 0 )) + newLine; outStream << "IsNpc=" + std::to_string(( IsNpc() ? 1 : 0 )) + newLine; outStream << "IsShop=" + std::to_string(( IsShop() ? 1 : 0 )) + newLine; @@ -4379,6 +4383,11 @@ bool CChar::HandleLine( std::string &UTag, std::string &data ) SetDead(( static_cast( std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 )) == 1 )); rValue = true; } + else if( UTag == "DEFCHANCE" ) + { + SetDefenseChance( static_cast( std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 ))); + rValue = true; + } break; case 'E': if( UTag == "EMOTION" ) @@ -4467,7 +4476,12 @@ bool CChar::HandleLine( std::string &UTag, std::string &data ) } break; case 'H': - if( UTag == "HUNGER" ) + if( UTag == "HITCHANCE" ) + { + SetHitChance( static_cast( std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 ))); + rValue = true; + } + else if( UTag == "HUNGER" ) { SetHunger( static_cast( std::stoi( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 ))); rValue = true; From 9b9f90d8b0a94efb6da4a33fdb96f6afdabdf73e Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Tue, 14 Jan 2025 23:28:03 -0600 Subject: [PATCH 6/7] update --- source/cBaseObject.cpp | 4 ++-- source/cChar.cpp | 2 +- source/combat.cpp | 12 +++++++++--- source/npcs.cpp | 2 ++ 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/source/cBaseObject.cpp b/source/cBaseObject.cpp index 9eedebfff..e98c3c693 100644 --- a/source/cBaseObject.cpp +++ b/source/cBaseObject.cpp @@ -1043,7 +1043,7 @@ void CBaseObject::IncHP( SI16 amtToChange ) //| Function - CBaseObject::GetHitChance() //| CBaseObject::SetHitChance() //o------------------------------------------------------------------------------------------------o -//| Purpose - Gets/Sets the Defense Chance of the Item Equiped +//| Purpose - Gets/Sets the Defense Chance of the Item(s) Equiped or Character //o------------------------------------------------------------------------------------------------o SI16 CBaseObject::GetHitChance( void ) const { @@ -1063,7 +1063,7 @@ void CBaseObject::SetHitChance( SI16 newValue ) //| Function - CBaseObject::GetDefenseChance() //| CBaseObject::SetDefenseChance() //o------------------------------------------------------------------------------------------------o -//| Purpose - Gets/Sets the Defense Chance of the Item Equiped +//| Purpose - Gets/Sets the Defense Chance of the Item(s) Equiped or Character //o------------------------------------------------------------------------------------------------o SI16 CBaseObject::GetDefenseChance( void ) const { diff --git a/source/cChar.cpp b/source/cChar.cpp index eb70922f6..3ae819d15 100644 --- a/source/cChar.cpp +++ b/source/cChar.cpp @@ -4383,7 +4383,7 @@ bool CChar::HandleLine( std::string &UTag, std::string &data ) SetDead(( static_cast( std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 )) == 1 )); rValue = true; } - else if( UTag == "DEFCHANCE" ) + else if( UTag == "DEFENSECHANCE" ) { SetDefenseChance( static_cast( std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 ))); rValue = true; diff --git a/source/combat.cpp b/source/combat.cpp index 066e3e80e..256f04c3c 100644 --- a/source/combat.cpp +++ b/source/combat.cpp @@ -2877,18 +2877,24 @@ bool CHandleCombat::HandleCombat( CSocket *mSock, CChar& mChar, CChar *ourTarg ) R32 attHitChanceBonus = 0; R32 defDefenseChanceBonus = 0; R32 maxAttHitChanceBonus = 45; + if( cwmWorldState->ServerData()->ExpansionCombatHitChance() >= ER_SA && mChar.GetBodyType() == BT_GARGOYLE ) { // If attacker is a Gargoyle player, and ExpansionCombatHitChance is ER_SA or higher, use 50 as hitchance bonus cap instead of 45 maxAttHitChanceBonus = 50; } - // Fetch bonuses to hitChance/defenseChance from AoS item properties + // Fetch bonuses to hitChance/defenseChance from AoS item properties or characters attHitChanceBonus = mChar.GetHitChance(); defDefenseChanceBonus = mChar.GetDefenseChance(); - R32 attackerHitChance = ( static_cast( attackSkill / 10 ) + 20 ) * ( 100 + std::min( attHitChanceBonus, static_cast( maxAttHitChanceBonus ))); - R32 defenderDefenseChance = ( static_cast( defendSkill / 10 ) + 20 ) * ( 100 + std::min( defDefenseChanceBonus, static_cast( 45 ))); + // Clamp to ensure valid bonus ranges (e.g., no multiplier below 1) + R32 effectiveAttHitChanceBonus = std::max(-99.0f, std::min( attHitChanceBonus, maxAttHitChanceBonus )); // Cap at -99 and maxAttHitChanceBonus + R32 effectiveDefDefenseChanceBonus = std::max(-99.0f, std::min( defDefenseChanceBonus, 45.0f )); // Cap at -99 and 45 + + // Calculate the attacker's hit chance and defender's defense chance + R32 attackerHitChance = ( static_cast( attackSkill / 10 ) + 20 ) * ( 100 + effectiveAttHitChanceBonus ); + R32 defenderDefenseChance = ( static_cast( defendSkill / 10 ) + 20 ) * ( 100 + effectiveDefDefenseChanceBonus ); hitChance = ( attackerHitChance / ( defenderDefenseChance * 2 )) * 100; // Always leave at least 2% chance to hit diff --git a/source/npcs.cpp b/source/npcs.cpp index 36005b420..a749b95aa 100644 --- a/source/npcs.cpp +++ b/source/npcs.cpp @@ -1541,6 +1541,8 @@ auto CCharStuff::ApplyNpcSection( CChar *applyTo, CScriptSection *NpcCreation, s case DFNTAG_NAMELIST: SetRandomName( applyTo, cdata ); break; case DFNTAG_NECROMANCY: skillToSet = NECROMANCY; break; case DFNTAG_NINJITSU: skillToSet = NINJITSU; break; + case DFNTAG_HITCHANCE: applyTo->SetHitChance( static_cast( ndata )); break; + case DFNTAG_DEFENSECHANCE: applyTo->SetDefenseChance( static_cast( ndata )); break; case DFNTAG_NPCWANDER: if( !isGate ) { From 127da5ccb8d4936e2c49a234e8a7b4160a4517da Mon Sep 17 00:00:00 2001 From: Dragon Slayer <85514184+DragonSlayer62@users.noreply.github.com> Date: Sat, 18 Jan 2025 13:25:57 -0600 Subject: [PATCH 7/7] fix --- source/cChar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/cChar.cpp b/source/cChar.cpp index 3ae819d15..eb70922f6 100644 --- a/source/cChar.cpp +++ b/source/cChar.cpp @@ -4383,7 +4383,7 @@ bool CChar::HandleLine( std::string &UTag, std::string &data ) SetDead(( static_cast( std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 )) == 1 )); rValue = true; } - else if( UTag == "DEFENSECHANCE" ) + else if( UTag == "DEFCHANCE" ) { SetDefenseChance( static_cast( std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 ))); rValue = true;