Skip to content

Commit

Permalink
Merge branch 'develop' into crystal-ball
Browse files Browse the repository at this point in the history
  • Loading branch information
Xoduz authored Dec 18, 2023
2 parents f28669b + bb42fac commit 041edd2
Show file tree
Hide file tree
Showing 10 changed files with 335 additions and 54 deletions.
116 changes: 116 additions & 0 deletions docs/jsdocs.html
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,122 @@ <h4>January 9th, 2022</h4>
</div> <!-- cd-faq__content -->
</li>

<li class="cd-faq__item">
<a class="cd-faq__trigger" href="#eventOnContextMenuRequest" id="eventOnContextMenuRequest"><span>onContextMenuRequest</span></a>
<div class="cd-faq__content">
<div class="text-component">
<div class="settingsDiv">
<p><span class="hl">Prototype</span></p>
<p><em>function onContextMenuRequest( socket, targObj )</em></p>
</div>
<div class="settingsDiv">
<p><span class="hl">Purpose</span></p>
<p>To allow reactions to player attempts at opening context menus for chars/items</p>
</div>
<div class="settingsDiv">
<p><span class="hl">When Triggered</span></p>
<p>When a player attempts to trigger context menu on items or characters, script activates on said item/character</p>
<p>Usable in Global script? <span class="hl">Yes</span></p>
</div>
<div class="settingsDiv">
<p><span class="hl">Return Values</span></p>
<ul>
<li><strong>return false</strong> to override and prevent hard-coded context menus from showing</li>
<li><strong>return true</strong> to let code handle context menu instead</li>
</ul>
</div>
<div class="settingsDiv">
<p><span class="hl">Example of usage</span><br>
<pre><code class="language-javascript">function onContextMenuRequest( socket, targObj )
{
// handle your own packet with context menu here
var pUser = socket.currentChar;
var offset = 12;
var numEntries = 1; // Increase with number of Entries

// Prepare packet
var toSend = new Packet();
var packetLen = ( 12 + ( numEntries * 8 ));
toSend.ReserveSize( packetLen );
toSend.WriteByte( 0, 0xBF );
toSend.WriteShort( 1, packetLen );
toSend.WriteShort( 3, 0x14 ); // subCmd
toSend.WriteShort( 5, 0x0001 ); // 0x0001 for 2D client, 0x0002 for KR (maybe this needs to be 0x0002?)
toSend.WriteLong( 7, targObj.serial );
toSend.WriteByte( 11, numEntries ); // Number of entries

// Context Menu Entry 1 - Open Paperdoll Context menu
toSend.WriteShort( offset, 0x000a ); // Unique ID
toSend.WriteShort( offset += 2, 6123);
toSend.WriteShort( offset += 2, 0x0020 ); // Flag, color enabled
toSend.WriteShort( offset += 2, 0x03E0 ); // Hue of text

offset += 2; // for each additional entry

// Context Menu Entry 2 - Unlink pet
toSend.WriteShort( offset, 0x000b ); // Unique ID
toSend.WriteShort( offset += 2, 6182 );
toSend.WriteShort( offset += 2, 0x0020 ); // Flag, color enabled
toSend.WriteShort( offset += 2, 0x03E0 ); // Hue of text

//Send packet
socket.Send( toSend );
toSend.Free();

return false;
}</code></pre></p>
</div>
</div>
</div> <!-- cd-faq__content -->
</li>

<li class="cd-faq__item">
<a class="cd-faq__trigger" href="#eventOnContextMenuSelect" id="eventOnContextMenuSelect"><span>onContextMenuSelect</span></a>
<div class="cd-faq__content">
<div class="text-component">
<div class="settingsDiv">
<p><span class="hl">Prototype</span></p>
<p><em>function onContextMenuSelect( socket, targObj, popupEntry )</em></p>
</div>
<div class="settingsDiv">
<p><span class="hl">Purpose</span></p>
<p>To allow custom handling of context menu selection for chars/items</p>
</div>
<div class="settingsDiv">
<p><span class="hl">When Triggered</span></p>
<p>When a player selects a popup from a context menu on an item/character, script activates on said item/character</p>
<p>Usable in Global script? <span class="hl">Yes</span></p>
</div>
<div class="settingsDiv">
<p><span class="hl">Return Values</span></p>
<ul>
<li><strong>return false</strong> to override and prevent hard-coded context menu selection handling</li>
<li><strong>return true</strong> to let code handle context menu selection handling</li>
</ul>
</div>
<div class="settingsDiv">
<p><span class="hl">Example of usage</span><br>
<pre><code class="language-javascript">function onContextMenuSelect( socket, targObj, popupEntry )
{
switch( popupEntry )
{
case 0x000A: // Open Paperdoll
// Show custom paperdoll?
break;
case 0x000B: // Unlink Pet
// Handle unlinking of pet here
break;
default:
break;
}

return false;
}</code></pre></p>
</div>
</div>
</div> <!-- cd-faq__content -->
</li>

<li class="cd-faq__item">
<a class="cd-faq__trigger" href="#eventOnContRemoveItem" id="eventOnContRemoveItem"><span>onContRemoveItem</span></a>
<div class="cd-faq__content">
Expand Down
92 changes: 80 additions & 12 deletions source/CPacketReceive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4589,19 +4589,50 @@ bool CPIPopupMenuRequest::Handle( void )
// Only show context menus if enabled in ini
if( !cwmWorldState->ServerData()->ServerContextMenus() )
return true;


CBaseObject *myObj = nullptr;

if( mSer < BASEITEMSERIAL )
{
CChar *myChar = CalcCharObjFromSer( mSer );
if( myChar == nullptr )
myObj = static_cast<CBaseObject*>( CalcCharObjFromSer( mSer ));
if( myObj == nullptr )
return true;

if( !LineOfSight( tSock, tSock->CurrcharObj(), myChar->GetX(), myChar->GetY(), ( myChar->GetZ() + 15 ), WALLS_CHIMNEYS + DOORS + FLOORS_FLAT_ROOFING, false ))
}
else
{
myObj = static_cast<CBaseObject*>( CalcItemObjFromSer( mSer ));
if( myObj == nullptr )
return true;

CPPopupMenu toSend(( *myChar ), ( *tSock ));
tSock->Send( &toSend );
}

std::vector<UI16> scriptTriggers = myObj->GetScriptTriggers();
for( auto scriptTrig : scriptTriggers )
{
cScript *toExecute = JSMapping->GetScript( scriptTrig );
if( toExecute != nullptr )
{
if( toExecute->OnContextMenuRequest( tSock, myObj ) == 0 )
{
return true;
}
}
}

// No individual scripts handling onContextMenu returned true - let's check global script!
cScript *toExecute = JSMapping->GetScript( static_cast<UI16>( 0 ));
if( toExecute != nullptr )
{
if( toExecute->OnContextMenuRequest( tSock, myObj ) == 0 )
{
return true;
}
}

if( !LineOfSight( tSock, tSock->CurrcharObj(), myObj->GetX(), myObj->GetY(), ( myObj->GetZ() + 15 ), WALLS_CHIMNEYS + DOORS + FLOORS_FLAT_ROOFING, false ))
return true;

CPPopupMenu toSend(( *myObj ), ( *tSock ));
tSock->Send( &toSend );
return true;
}
void CPIPopupMenuRequest::Log( std::ostream &outStream, bool fullHeader )
Expand Down Expand Up @@ -4631,18 +4662,27 @@ void CPIPopupMenuRequest::Log( std::ostream &outStream, bool fullHeader )
//| BYTE[4] Character ID
//| BYTE[2] Entry Tag for line selected provided in subcommand 0x14
//o------------------------------------------------------------------------------------------------o
CPIPopupMenuSelect::CPIPopupMenuSelect() : popupEntry( 0 ), targChar( nullptr )
CPIPopupMenuSelect::CPIPopupMenuSelect() : popupEntry( 0 ), targObj( nullptr )
{
}
CPIPopupMenuSelect::CPIPopupMenuSelect( CSocket *s ) : CPInputBuffer( s ), popupEntry( 0 ), targChar( nullptr )
CPIPopupMenuSelect::CPIPopupMenuSelect( CSocket *s ) : CPInputBuffer( s ), popupEntry( 0 ), targObj( nullptr )
{
Receive();
}

void CPIPopupMenuSelect::Receive( void )
{
popupEntry = tSock->GetWord( 9 );
targChar = CalcCharObjFromSer( tSock->GetDWord( 5 ));

SERIAL mSer = tSock->GetDWord( 5 );
if( mSer < BASEITEMSERIAL )
{
targObj = static_cast<CBaseObject*>( CalcCharObjFromSer( mSer ));
}
else
{
targObj = static_cast<CBaseObject*>( CalcItemObjFromSer( mSer ));
}
}

bool WhichResponse( CSocket *mSock, CChar *mChar, std::string text, CChar *tChar = nullptr );
Expand All @@ -4653,9 +4693,37 @@ bool CPIPopupMenuSelect::Handle( void )
return true;

CChar *mChar = tSock->CurrcharObj();
if( !ValidateObject( targChar ) || !ValidateObject( mChar ))
if( !ValidateObject( targObj ) || !ValidateObject( mChar ))
return true;

std::vector<UI16> scriptTriggers = targObj->GetScriptTriggers();
for( auto scriptTrig : scriptTriggers )
{
cScript *toExecute = JSMapping->GetScript( scriptTrig );
if( toExecute != nullptr )
{
if( toExecute->OnContextMenuSelect( tSock, targObj, popupEntry ) == 0 )
{
return true;
}
}
}

// No individual scripts handling onContextMenu returned true - let's check global script!
cScript *toExecute = JSMapping->GetScript( static_cast<UI16>( 0 ));
if( toExecute != nullptr )
{
if( toExecute->OnContextMenuSelect( tSock, targObj, popupEntry ) == 0 )
{
return true;
}
}

if( targObj->CanBeObjType( OT_ITEM )) // No items with hard coded context menus
return true;

CChar *targChar = static_cast<CChar *>( targObj );

switch( popupEntry )
{
case 0x000A: // Open Paperdoll
Expand Down
2 changes: 1 addition & 1 deletion source/CPacketReceive.h
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,7 @@ class CPIPopupMenuSelect : public CPInputBuffer
{
protected:
UI16 popupEntry;
CChar * targChar;
CBaseObject * targObj;
public:
virtual ~CPIPopupMenuSelect()
{
Expand Down
Loading

0 comments on commit 041edd2

Please sign in to comment.