Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

[Tutorial] Teleport commands / Coding for kal 101

Modeler / C++ Coder
Developer
Joined
Feb 6, 2008
Messages
561
Reaction score
483
I know for a fact there is some source for the same thing roaming about made by Darn,
but because I know that source is quite "messy" it might not be easy for everyone to understand what he does and why.

so that's why ill show my way of coding a small addon like the teleport commands just to give a 101 clear example on how I usualy do it!

1) first of all you'll need a hook on the chat command to then ofc add your code for the teleports in! also youll need the serverstart to create/initialize the teleports and serverstop to deallocate/destroy them.
if you don't know what I mean by that don't worry ill explain it while we go!

I'm jumping of MadKnight's Detouring tutorial.
http://forum.ragezone.com/f554/howto-detour-kal-mainserver-892220/

you'll need a basic project like that to start off!.

when you have the basic project ready, youll need to create a new header file.
this header file will be used for all the mainserver function defenitions!

// Filename : ServerFunctions.h
#ifndef _SERVERFUNCTIONS_H_
#define _SERVERFUNCTIONS_H_

#include <windows.h>

namespace
MainServer
{
// here ill define the server start and stop functions wich ill need later to hook them!
static void(__stdcall*Start)(int start) = (void (__stdcall*)(intstart))0x00424A40;
static int(__thiscall*Stop)(intstop) = (int (__thiscall*)(intstop))0x00424BA0;
}

namespace CPlayer
{
// here ill define the player functions I need (just 2 for this tut!)
static int (__thiscall *ChatCommand)(int* playerptr, const char* command) = (int (__thiscall*)(int*, const char*))0x00461080;
static int (__thiscall *Teleport)(int playerptr, int mapnum, int coords, int a4, int a5) = (int (__thiscall*)(int, int, int, int, int))0x0045CC90;
}

namespace CChar
{
static int (__thiscall *IsGState)(int playerptr, int state) = (int (__thiscall*)(int, int))0x0040B310;​
}

#endif

now that we have the header file with the function declares we need for the hooking we can start creating the hooks in the maindll.cpp file! :thumbup1:

// Filename: maindll.cpp
#include"stdafx.h"

#pragma comment(lib, "detours.lib")

#undefUNICODE
#include<cstdio>
#include<windows.h>
#include <detours.h>
#include <process.h>

#pragma pack(1)

#include <string>

// here I include the serverfunctions file created earlier
#include "ServerFunctions.h"

// here I include the teleports header and define a handle for it but its not initialized yet!
#include "TeleCommand.h"
TeleCommand* telecommand;

// here ill create the new server start function wich will contain the constructor call for the teleports
void __stdcall Hooked_Mainserver_Start(int start)
{
// like madknight explained in his tut aswell we need to call the original start function for the server to actualy continue starting!
MainServer::Start(start);

// now after the server is started I also want to create my teleport class object and initialize them!
telecommand = new TeleCommand;
telecommand->Initialize();
}

// and ofc with a start there comes a stop! we need the stop function to clean up after ourselves when the server shuts down!
int __fastcall Hooked_MainServer_Stop(int stop)
{
// here ill check if the teleport object exists when the server stop is called, if it exists it needs to be destroyed before the server stops
// if I would not delete the object here it would "leak" the memory because its never deallocated

if(telecommand)
{​
// call the shutdown for the actual teleport structs deallocation
telecommand->Shutdown()
// delete the telecommand object
delete telecommand;
// and set the pointer to 0 (get used to do this its cleaner) because its not existing anymore
telecommand = 0;​
}

// call and return the original server stop function
return ServerStop(stop);​
}

// here we hook the chatcommand function to add in the teleport function
void __fastcall Hooked_CPlayer_ChatCommand(int playerptr, int, const char *command)
{
// cast the command to a std::string variable
std::string str = command;


// check if the playerptr is not 0. (will couse a crash if it is!)

if(playerptr)
{​
// check if the player is in assassin state! if it is then just skip the teleporting function
if( !CChar::IsGState(playerptr, 256) )
{​
// if the player is not in assa state we can start our teleport commands loop! it loops as many times as there are teleports allocated and initialized!
for(int i = 0; i < telecommand->GetTeleCount(); i++ )
{
// here i grab the digits in the command with the size of the teleport command at that index
std::string TeleCommand = str.substr(0, telecommand->GetTeleCommand(i).length());

// now we can compare the commands and see if they are the same
if( TeleCommand == telecommand->GetTeleCommand(i) )
{
// if they are the same then teleport the player to the location of the teleport at that index!

int coords[2];
coords[0] = telecommand->GetCoordX();
coords[1] = telecommand->GetCoordY();


CPlayer::Teleport(playerptr, telecommand->GetMap(), (int)coords, 0, 1);
}
}
}​
}

// call the original chatcommand server in the mainserver otherwise old commands don't work! (because its a void I don't need to return this one)
CPlayer::ChatCommand(playerptr, command);​
}

BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)MainServer::Start, Hooked_MainServer_Start);
DetourAttach(&(PVOID&)MainServer::Stop, Hooked_MainServer_Stop);
DetourAttach(&(PVOID&)CPlayer::ChatCommand, Hooked_CPlayer_CharCommand);

DetourTransactionCommit();
break;
}
case DLL_PROCESS_DETACH:
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)Mainserver::Start, Hooked_MainServer_Start);
DetourDetach(&(PVOID&)MainServer::Stop, Hooked_MainServer_Stop);
DetourDetach(&(PVOID&)CPlayer::ChatCommand, Hooked_CPlayer_CharCommand);


DetourTransactionCommit();
break;
}
}
return TRUE;
}

2) now that we have the main part of the dll done and the hooks in place we need the actual TeleCommand class, this class contains all the funtions i need to construct, initialize, destruct and use the teleport commands!
so we need a new header file for the new class, create a new .h file and call it TeleCommand.h.

// Filename: TeleCommand.h
#ifndef _TELECOMMAND_H_
#define _TELECOMMAND_H_

#include<windows.h>

class TeleCommand
{
private:
// here i create a private struct Teleport wich contains all the variables we need for a teleport command
struct
Teleport
{
std::string Command;
int MapNum;
int CoordX;
int CoordY;
};
public:
// here i declare all the functions we need in this class
TeleCommand();
TeleCommand(
const TeleCommand&);
~TeleCommand();

void Initialize();
void Shutdown();

int GetTeleCount();

std::string GetTeleCommand(
int index);
int GetMap(int index);
int GetCoordX(int index);
int GetCoordY(int index);
private:
// and here i declare the variables needed, a count to see how many different teleports we have, and a handle to store the actual structs under.
int TeleCount;
Teleport* m_teleport;
}

#endif

3)now that i have the header completed ill continue with the actual cpp file and functions declerations.
create a new cpp file and name it TeleCommand.cpp.

// Filename: TeleCommand.cpp
#include"StdAfx.h"
#include"TeleCommand.h"
#include <fstream>

TeleCommand::TeleCommand()
{
// here i initialize the variables to 0 on the object construction
TeleCount = 0;
m_teleport = 0;​
}

TeleCommand::TeleCommand(const TeleCommand& other)
{
}

TeleCommand::~TeleCommand()
{
}

// the initialize function will read out the config and create and fill the teleport structs depending on how many teleport commands you want to add ofc
void TeleCommand::Initialize()
{
// create the file reader and open the config
std::ifstream TeleRead;
TeleRead.open("./MatyConfig/TeleportCommand.txt");

// check if it opened the file or if it could not open it
if(TeleRead)
{​
// read out how many teleport commands there are out of the file (first value in the config)
TeleRead >> TeleCount;

// now we know how many teleports there are in the file we can allocate the structs that will contain them with the TeleCount variable
m_teleport = new Teleport[TeleCount];

// now that we have the structs allocated its time to fill them with data out of the config file using a for loop!
for(int i = 0; i < TeleCount; i++)
{​
// read out the rest of the config line by line and store the data in the structs at the correct index
TeleRead >> m_teleport.Command >> m_teleport.MapNum >> m_teleport.CoordX >> m_teleport.CoordY;

}

// and ofc don't forget to close the file
TeleRead.close()​
}​
}

// we also need a shutdown function to deallocate the teleport structs when the server shuts down!
void TeleCommand::Shutdown()
{
// like usual i check if the data actualy exists.
if(m_teleport)
{​
// if it exists, delete it because we don't want it left in memory after the server is down and set the pointer to 0
delete [] m_teleport;
m_teleport = 0;​
}​
}

// now we need to create all the functions to access the data in the structs and this class and return it
int TeleCommand::GetTeleCount()
{
// return the TeleCount variable
returnTeleCount;​
}

std::string TeleCommand::GetTeleCommand(
int index)
{
// get and return the command variable at the given index from the struct
return m_teleport[index].Command;
}

int TeleCommand::GetMap(int index)
{
// get and return the MapNum variable at the given index from the struct
return m_teleport[index].MapNum;
}

int TeleCommand::GetCoordX(
int index)
{
// get and return the CoordX variable at the given index from the struct
return m_teleport[index].CoordX;
}

int TeleCommand::GetCoordY(
int index)
{
// get and return the CoordY variable at the given index from the struct
return m_teleport[index].CoordY;
}

beleave it or not that is actualy all the coding done!

4) all you need now is to compile it and include it into your mainserver with obsidian or so. but don't forget to add the config!

heres an example of how that file should look like:

Code:
2
/test1 0 268329 240503
/test2 0 256876 258710

the first variable is the telecount
the rest are the lines of data you need for the teleports itself ofc :)

5) hope you had fun with this small example of how i code, and i sure hope you learned something.
now all you got left to do is practice and code your own stuff!

Hail to the king!

Best regards,

Matynator
 
Last edited:
Elite Diviner
Joined
Sep 14, 2006
Messages
429
Reaction score
273
3ds max importer with working weights
Matynator - [Tutorial] Teleport commands / Coding for kal 101 - RaGEZONE Forums
 
Newbie Spellweaver
Joined
Jun 30, 2007
Messages
76
Reaction score
74
Next tut: how to code importer for 3d max useing released kalonline source code.
 
Elite Diviner
Joined
Feb 28, 2013
Messages
401
Reaction score
145
I think you could do tutorial about creating Buff Event dll :thumbup:


Kind Regards,
ItsTaP.
 
Elite Diviner
Joined
Feb 28, 2013
Messages
401
Reaction score
145
hmmmm sorry Trocin & kal section didn't notice that , thanks for replying me anyways Trocin :)


Kind Regards,
ItsTaP
 
Back
Top