Jump to content

Recommended Posts

Posted (edited)

Preface

This guide starts with the basis that you already know of WOTExplorer and have experience with decompiling/compiling interface scripts from interface.u.

If you have not done this before please visit here:

This is a good collection of all the Compilers, and comes with clean interface scripts based on your Client Version. To edit different scripts mentioned in this Guide from the above download, you will navigate to:

Main Compiler Folder > Interface > Classes

These are all the scripts housed within Interface.u

Upon completion of editing, and wanting to build a new Interface.u to put into your Clients main System folder, you will then navigate to:

Main Compiler Folder > System > Make_Interface.bat

 

This will also alert you of any errors in your code to correct, as if the code won't compile correctly it won't build your new Interface.u

 

------------------------------------


On with the Guide

The method we'll use within this guide to communicate between the Game Server, and the Lineage II Client is the Piggy Back method. We'll be Piggybacking on an existing event that already exists within the game that the client listens for. The Event we'll be piggybacking on is the EV_TutorialViewerWndShow.

What does this mean? Well the client and pretty much all server files already have handlers implemented to allow communication for the main Tutorial Quest in the game, that will pop-up the tutorial window in-game. You may wonder how this helps us accomplish our goal, and it's very simple.

The way this function works by default is the server packages a html String and sends it with the event OPCode to the client. The client registers the event and when it triggers will parse that String data and show it as a Tutorial Window.

What we intend to do, is instead of just sending a static html string, we will add a Header Element, and some new OPCode's of our own, that when the event triggers on the client we can modify the TutorialViewerWnd.uc script to check for these headers. If they exist, do our own custom logic, and if they don't continue on with the basic logic already implemented to handle the Tutorial Window.

 


------------------------------------


First, Let's handle the Server Side Code

Typically a Server will send the tutorial message kind of like this:

player.sendPacket(new TutorialShowHtml(HtmCache.getInstance().getHtmForce("data/html/script/feature/Tutorial/" + html)));

 

As you can see it sends a new Client based packet with the tutorial html string, but as stated it's just a String, so we can send any type of string we want.

Example:
 

player.sendPacket(new TutorialShowHtml("UC" + "|" + "value"));


Now by default the client won't know how to handle this and will most definitely throw an error, but what this represents is UC as a header, | as an iterator, and value as a variable we want to pass.

 


------------------------------------


Now lets handle processing it on the Client within TutorialViewerWnd.uc:

 

Within the function OnEvent and within the switch case EV_TutorialViewerWndShow we're going to add a new check and rearrange the logic a bit.

We're going to use the UnrealScript function called Split, what this does is allows us to use an iterator to break up a string into an array of separate strings, using the iterator as a way of separating them, in our case the "|".

Example:
 

local String sampleString = "Yul|Is|A Really|Cool|Dude";
local array<String> dataArray;

Split(sampleString, "|", dataArray;

Output would be:

dataArray[0] == "Yul"
dataArray[1] == "Is"
dataArray[2] == "A Really"

etc..


So with that knowledge, we can now use a header followed by a value to send data to the client to be used. This can be anything from Strings/Integers etc for information like Premium Time, Rates, Maybe player stats if you want a better stat window etc.

So how do we catch and handle it in the OnEvent Script? Simple.

Example:
 

function OnEvent( int Event_ID, string param )
{
	local string HtmlString;
	local array<string> dataArray;

	switch( Event_ID )
	{
		case EV_TutorialViewerWndShow :
			ParseString(param, "HtmlString", HtmlString);
			Split(HtmlString, "|", dataArray);
			
			// Check for Custom Logic
			if(dataArray[0] == "UC")
			{
				CustomVariableLogic(dataArray);
			}
			else
			{
				StandardEventLogic(HtmlString);
			}
			
			break;
		case EV_TutorialViewerWndHide :
			HideWindow("TutorialViewerWnd");
			break;
	}
}


We move all the basic logic that previously existed into its own function called StandardEventLogic(), re-passing in the HtmlString for it do do its thing, otherwise, we'll pass the dataArray.

With the array, we know index of 0 is our header in this case "UC" for Unchained, when then can have endless variables all using a Post ("|") as an iterator to separate them.

Within our customVariableLogic, we can further use switches for our own custom OpCodes, in my example I use index 1 (The second value in the string) to be the OPCode for our custom logic to switch upon, allowing different functions to handle different things.

Example:
 

/*
*	CUSTOM
*	This script is ran if custom variable based commands come through the TutorialEvent
*/
function CustomVariableLogic (array<string> dataArray)
{
	local int OPCode;
	local string data1, data2;

	// Initialize Values
	OPCode = int(dataArray[1]);
	data1 = dataArray[2];
	data2 = dataArray[3];
	
	// Switch on Action
	switch( OPCode )
	{
		// Pass Premium Information to the Character Status Window
		case 1:
			UpdatePremiumStatusInfo(data1, data2);
		break;
	}
}


Ok now we know how to pass data from the Server to the Client, sweet. But now how can we pass information back to the Server, from the client? Well it's actually even easier. What we do within the client script is call RequestBypassToServer() what this does is allows you to send custom logic back to the server, which can then be processed by the server.

Some examples of things that already use RequestBypassToServer are you admin commands, etc. Most server files even call the the handler RequestBypassToServer, so you can search for that within your server files.

Example of how it catches it is:
 

if (_command.startsWith("admin_"))
{
  	// Logic Here
}


If our case we'd want to add a new one
 

if (_command.startsWith("admin_"))
{
  	// Logic here
}
else if (_command.equals("UC_charPanel"))
{
	// Logic to handle, or can even use antoher Tutorial packet back to the server
}


On the client, we could have a button that we want to open the charPanel using this serverside code to handle it.
 

function OnClickButton( string strID )
{	
	switch( strID )
	{
		case "AccountButton":
			RequestBypassToServer("UC_charPanel");
			break;
	}
}


Hope this guide helps out anyone new to client development, there is a lot to take in, and not a whole lot of guides out there for things. So hope this one can be a good starting point for any newbies out there.

Cheers,
YulRun

 

Edited by YulRun
Formatting
  • Like 4
  • Thanks 1
  • Upvote 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...