Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hit/Defense Chance Properties #290

Merged
merged 10 commits into from
Jan 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 33 additions & 19 deletions source/CPacketSend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ using namespace std::string_literals;
//| BYTE[2] unknown5 (0x0)
//| BYTE[4] unknown6 (0x0)
//|
//| Note: Only send once after login. It’s mandatory to send it once.
//| Note: Only send once after login. It’s mandatory to send it once.
//o------------------------------------------------------------------------------------------------o
void CPCharLocBody::Log( std::ostream &outStream, bool fullHeader )
{
Expand Down Expand Up @@ -1411,7 +1411,7 @@ CPPaperdoll &CPPaperdoll::operator = ( CChar &toCopy )
//|
//| Packet Build
//| BYTE cmd
//| BYTE type (0x00 – “It starts to rain”, 0x01 – “A fierce storm approaches., 0x02 – “It begins to snow”, 0x03 - “A storm is brewing., 0xFF None (turns off sound effects), 0xFE (no effect?? Set temperature?)
//| BYTE type (0x00 – “It starts to rain”, 0x01 – “A fierce storm approaches.”, 0x02 – “It begins to snow”, 0x03 - “A storm is brewing.”, 0xFF – None (turns off sound effects), 0xFE (no effect?? Set temperature?)
//| BYTE num (number of weather effects on screen)
//| BYTE temperature
//|
Expand All @@ -1422,8 +1422,8 @@ CPPaperdoll &CPPaperdoll::operator = ( CChar &toCopy )
//| Note: Weather messages are only displayed when weather starts.
//| Note: Weather will end automatically after 6 minutes without any weather change packets.
//| Note: You can totally end weather (to display a new message) by teleporting.
//| I think it’s either the 0x78 or 0x20 messages that reset it, though I
//| haven’t checked to be sure (other possibilities, 0x4F or 0x4E)
//| I think it’s either the 0x78 or 0x20 messages that reset it, though I
//| haven’t checked to be sure (other possibilities, 0x4F or 0x4E)
//o------------------------------------------------------------------------------------------------o
void CPWeather::InternalReset( void )
{
Expand Down Expand Up @@ -2043,7 +2043,7 @@ void CPOpenGump::Serial( SERIAL toSet )
//| BYTE unknown (0x00)
//| BYTE click zLoc
//| BYTE[2] model # (if a static tile, 0 if a map/landscape tile)
//| Note: the model # shouldn’t be trusted.
//| Note: the model # shouldn’t be trusted.
//o------------------------------------------------------------------------------------------------o
CPTargetCursor::CPTargetCursor()
{
Expand Down Expand Up @@ -2601,7 +2601,7 @@ void CPStatWindow::TithingPoints( UI32 value )
//| 0x07 idle
//| 0x05 another character is online
//| "Another character from this account is currently online in this world.
//| You must either log in as that character or wait for it to time out.
//| You must either log in as that character or wait for it to time out.”
//o------------------------------------------------------------------------------------------------o
void CPIdleWarning::InternalReset( void )
{
Expand Down Expand Up @@ -3107,12 +3107,12 @@ CPMultiPlacementView::CPMultiPlacementView( SERIAL toSet )
//| 0 neither T2A NOR LBR, equal to not sending it at all,
//| 1 is T2A, chatbutton,
//| 2 is LBR without chatbutton,
//| 3 is LBR with chatbutton…
//| 3 is LBR with chatbutton…
//| 8013 LBR + chatbutton + AOS enabled
//|
//| Note1: this message is send immediately after login.
//| Note2: on OSI servers this controls features OSI enables/disables via “upgrade codes.
//| Note3: a 3 doesn’t seem to “hurt” older (NON LBR) clients.
//| Note2: on OSI servers this controls features OSI enables/disables via “upgrade codes.”
//| Note3: a 3 doesn’t seem to “hurt” older (NON LBR) clients.
//o------------------------------------------------------------------------------------------------o
CPEnableClientFeatures::CPEnableClientFeatures( CSocket *mSock )
{
Expand Down Expand Up @@ -6118,7 +6118,7 @@ void CPObjectInfo::Objects( CItem& mItem, CChar& mChar )
//| BYTE[2] Font
//| BYTE[4] Language
//| BYTE[30] Name
//| BYTE[?][2] Msg Null Terminated (blockSize - 48)
//| BYTE[?][2] Msg – Null Terminated (blockSize - 48)
//|
//| The various types of text is as follows:
//| 0x00 - Normal
Expand Down Expand Up @@ -6294,7 +6294,7 @@ void CPUnicodeSpeech::GhostIt( [[maybe_unused]] UI08 method )
//| BYTE[2] Font
//| BYTE[4] Language
//| BYTE[30] Name
//| BYTE[?][2] Msg Null Terminated (blockSize - 48)
//| BYTE[?][2] Msg – Null Terminated (blockSize - 48)
//|
//| The various types of text is as follows:
//| 0x00 - Normal
Expand Down Expand Up @@ -6572,7 +6572,7 @@ void CPSecureTrading::Name( const std::string& nameFollowing )
//o------------------------------------------------------------------------------------------------o
//| Purpose - Handles outgoing packet with server response to all names request
//o------------------------------------------------------------------------------------------------o
//| Notes - Packet: 0x98 (All-names “3D”)
//| Notes - Packet: 0x98 (All-names “3D”)
//| Size: Variable
//|
//| Packet Build
Expand All @@ -6588,7 +6588,7 @@ void CPSecureTrading::Name( const std::string& nameFollowing )
//| Client asks for name of object with ID x.
//| Server has to reply with ID + name
//| Client automatically knows names of items.
//| Hence it only asks only for NPC/Player names nearby, but shows bars of items plus NPC’s.
//| Hence it only asks only for NPC/Player names nearby, but shows bars of items plus NPC’s.
//|
//| Client request has 7 bytes, server-reply 37
//| Triggered by Crtl + Shift.
Expand Down Expand Up @@ -6641,7 +6641,7 @@ void CPAllNames3D::Object( CBaseObject& obj )
//| BYTE[var] null terminated line
//| Note:
//| server side: # of pages equals value given in 0x93/0xd4
//| EACH page # given. If empty: # lines: 0 + terminator (=3 0’s)
//| EACH page # given. If empty: # lines: 0 + terminator (=3 0’s)
//| client side: # of pages always 1. if 2 pages changed, client generates 2 packets.
//o------------------------------------------------------------------------------------------------o
void CPBookPage::IncLength( UI08 amount )
Expand Down Expand Up @@ -7009,7 +7009,7 @@ bool CPNewSpellBook::ClientCanReceive( CSocket *mSock )
//| BYTE[4] Serial
//| BYTE Damage // how much damage was done ?
//|
//| Note: displays damage above the npc/player’s head.
//| Note: displays damage above the npc/player’s head.
//o------------------------------------------------------------------------------------------------o
void CPDisplayDamage::InternalReset( void )
{
Expand Down Expand Up @@ -7665,6 +7665,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.GetHealthBonus() > 0 )
{
tempEntry.stringNum = 1060431; // hit point increase ~1_val~
Expand Down Expand Up @@ -8057,9 +8071,9 @@ bool CPSellList::CanSellItems( CChar &mChar, CChar &vendor )
//| BYTE[2] len
//| BYTE subcmd
//| BYTE[ len - 4 ] submessage
//| Submessage 0 Display Bulletin Board
//| Submessage 0 – Display Bulletin Board
//| BYTE[4] Board serial
//| BYTE[22] board name (default is “bulletin board”, the rest nulls)
//| BYTE[22] board name (default is “bulletin board”, the rest nulls)
//| BYTE[4] unknown/ID?
//| BYTE[4] zero (0)
//o------------------------------------------------------------------------------------------------o
Expand Down Expand Up @@ -8139,7 +8153,7 @@ CPOpenMessageBoard::CPOpenMessageBoard( CSocket *mSock )
//| BYTE subjectLen
//| BYTE[subjectLen] subject (null terminated string)
//| BYTE timeLen
//| BYTE[timeLen] time (null terminated string with time of posting) (“Day 1 @ 11:28”)
//| BYTE[timeLen] time (null terminated string with time of posting) (“Day 1 @ 11:28”)
//o------------------------------------------------------------------------------------------------o
//| Subcommand: 0x2 (Message Summary)
//| Size: Variable
Expand All @@ -8156,7 +8170,7 @@ CPOpenMessageBoard::CPOpenMessageBoard( CSocket *mSock )
//| BYTE subjectLen
//| BYTE[subjectLen] subject (null terminated string)
//| BYTE timeLen
//| BYTE[timeLen] time (null terminated string with time of posting) (“Day 1 @ 11:28”)
//| BYTE[timeLen] time (null terminated string with time of posting) (“Day 1 @ 11:28”)
//| BYTE[5] Unknown (01 90 03 F7 00)
//| BYTE numlines
//| For each line:
Expand Down
6 changes: 6 additions & 0 deletions source/Changelog.txt
Original file line number Diff line number Diff line change
@@ -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

13/06/2024 - Dragon Slayer
Added three More AOS Props
-HEALTHBONUS=#
Expand Down
5 changes: 5 additions & 0 deletions source/UOXJSPropertyEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,8 @@ enum CC_Properties
CCP_SPAWNSERIAL,
CCP_SPATTACK,
CCP_SPDELAY,
CCP_HITCHANCE,
CCP_DEFENSECHANCE,
CCP_AITYPE,
CCP_SPLIT,
CCP_SPLITCHANCE,
Expand Down Expand Up @@ -461,6 +463,9 @@ enum CI_Properties
CIP_DAMAGEPOISON,
CIP_DAMAGERAIN,
CIP_DAMAGESNOW,
CIP_HITCHANCE,
CIP_DEFENSECHANCE,

CIP_ARTIFACTRARITY,
CIP_NAME2,
CIP_ISITEM,
Expand Down
10 changes: 10 additions & 0 deletions source/UOXJSPropertyFuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -676,10 +676,13 @@ 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_HEALTHBONUS: *vp = INT_TO_JSVAL( gPriv->GetHealthBonus() ); break;
case CIP_STAMINABONUS: *vp = INT_TO_JSVAL( gPriv->GetStaminaBonus() ); break;
case CIP_MANABONUS: *vp = INT_TO_JSVAL( gPriv->GetManaBonus() ); break;
case CIP_ARTIFACTRARITY: *vp = INT_TO_JSVAL( gPriv->GetArtifactRarity() ); break;

case CIP_NAME2:
tString = JS_NewStringCopyZ( cx, gPriv->GetName2().c_str() );
*vp = STRING_TO_JSVAL( tString );
Expand Down Expand Up @@ -1325,10 +1328,13 @@ 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<UI08>( encaps.toInt() )); break;
case CIP_HITCHANCE: gPriv->SetHitChance( static_cast<SI16>( encaps.toInt() )); break;
case CIP_DEFENSECHANCE: gPriv->SetDefenseChance( static_cast<SI16>( encaps.toInt() )); break;
case CIP_HEALTHBONUS: gPriv->SetHealthBonus( static_cast<SI16>( encaps.toInt() )); break;
case CIP_STAMINABONUS: gPriv->SetStaminaBonus( static_cast<SI16>( encaps.toInt() )); break;
case CIP_MANABONUS: gPriv->SetManaBonus( static_cast<SI16>( encaps.toInt() )); break;
case CIP_ARTIFACTRARITY: gPriv->SetArtifactRarity( static_cast<SI16>( encaps.toInt() )); break;

case CIP_NAME2: gPriv->SetName2( encaps.toString() ); break;
case CIP_RACE: gPriv->SetRace( static_cast<RACEID>( encaps.toInt() )); break;
case CIP_MAXHP: gPriv->SetMaxHP( static_cast<SI16>( encaps.toInt() )); break;
Expand Down Expand Up @@ -2002,6 +2008,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;
Expand Down Expand Up @@ -2507,6 +2515,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<SI16>( encaps.toInt() )); break;
case CCP_SPDELAY: gPriv->SetSpDelay( static_cast<SI08>( encaps.toInt() )); break;
case CCP_HITCHANCE: gPriv->SetHitChance( static_cast<SI16>( encaps.toInt() )); break;
case CCP_DEFENSECHANCE: gPriv->SetDefenseChance( static_cast<SI16>( encaps.toInt() )); break;
case CCP_AITYPE: gPriv->SetNPCAiType( static_cast<SI16>( encaps.toInt() )); break;
case CCP_SPLIT: gPriv->SetSplit( static_cast<UI08>( encaps.toInt() )); break;
case CCP_SPLITCHANCE: gPriv->SetSplitChance( static_cast<UI08>( encaps.toInt() ));break;
Expand Down
7 changes: 7 additions & 0 deletions source/UOXJSPropertySpecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down Expand Up @@ -535,10 +537,15 @@ 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 },

{ "healthBonus", CIP_HEALTHBONUS, JSPROP_ENUMANDPERM, nullptr, nullptr },
{ "staminaBonus", CIP_STAMINABONUS, JSPROP_ENUMANDPERM, nullptr, nullptr },
{ "manaBonus", CIP_MANABONUS, JSPROP_ENUMANDPERM, nullptr, nullptr },
{ "artifactRarity", CIP_ARTIFACTRARITY, 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 },
Expand Down
66 changes: 65 additions & 1 deletion source/cBaseObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ 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;

const SI16 DEFBASE_HEALTHBONUS = 0;
const SI16 DEFBASE_STAMINABONOS = 0;
const SI16 DEFBASE_MANABONUS = 0;
Expand All @@ -114,7 +118,7 @@ mana( DEFBASE_MANA ), stamina( DEFBASE_STAMINA ), scriptTrig( DEFBASE_SCPTRIG ),
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 ),
healthBonus( DEFBASE_HEALTHBONUS ),staminaBonus( DEFBASE_STAMINABONOS ), manaBonus( DEFBASE_MANABONUS )
healthBonus( DEFBASE_HEALTHBONUS ),staminaBonus( DEFBASE_STAMINABONOS ), manaBonus( DEFBASE_MANABONUS ), hitChance( DEFBASE_HITCHANCE ), defenseChance( DEFBASE_DEFENSECHANCE )
{
multis = nullptr;
tempMulti = INVALIDSERIAL;
Expand Down Expand Up @@ -1040,6 +1044,46 @@ void CBaseObject::IncHP( SI16 amtToChange )
SetHP( hitpoints + amtToChange );
}

//o------------------------------------------------------------------------------------------------o
//| Function - CBaseObject::GetHitChance()
//| CBaseObject::SetHitChance()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets/Sets the Defense Chance of the Item(s) Equiped or Character
//o------------------------------------------------------------------------------------------------o
SI16 CBaseObject::GetHitChance( void ) const
{
return hitChance;
}
void CBaseObject::SetHitChance( SI16 newValue )
{
hitChance = newValue;

if( CanBeObjType( OT_ITEM ))
{
( static_cast<CItem *>( this ))->UpdateRegion();
}
}

//o------------------------------------------------------------------------------------------------o
//| Function - CBaseObject::GetDefenseChance()
//| CBaseObject::SetDefenseChance()
//o------------------------------------------------------------------------------------------------o
//| Purpose - Gets/Sets the Defense Chance of the Item(s) Equiped or Character
//o------------------------------------------------------------------------------------------------o
SI16 CBaseObject::GetDefenseChance( void ) const
{
return defenseChance;
}
void CBaseObject::SetDefenseChance( SI16 newValue )
{
defenseChance = newValue;

if( CanBeObjType( OT_ITEM ))
{
( static_cast<CItem *>( this ))->UpdateRegion();
}
}

//o------------------------------------------------------------------------------------------------o
//| Function - CBaseObject::GetDir()
//| CBaseObject::SetDir()
Expand Down Expand Up @@ -1728,6 +1772,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
Expand Down
Loading
Loading