View Single Post
  #5  
Old 01-19-2008, 03:19 AM
Bulle
Hill Giant
 
Join Date: Jan 2008
Posts: 102
Default How to implement the Character Creation hook

To ensure the rules hook worked I included one hook, during the character creation. Why there ? Because I had problems running "zone" under Linux (my installatio's fault most certainly), so I chose one place I would easily access in "world". Plus I want to make everyone a ranger !
This hook is inserted into the character creation process, right after the server checks for cheaters (it checks whether the stats provided are possible), and before the character is actually created. Now that we are sure the guy at the other end is not cheating, we can change his character how we see fit.
This hook function signature is simple : it receives the CharInfo_Struct pointer and can fiddle with it however it wants. The function returns nothing, it works by altering the CharInfo_Struct. The hook signature is :
Code:
void default_CharacterCreation_ChangeCreationInfo(CharCreate_Struct *cc);
The default implementation does nothing. The character is created as the player asked.
My Hero server forces him to be a ranger !
To implement the hook (the first hook is of course the longest), you must create a new project for your rules shared library. On Windows I created a new project named "Hero", and made every single setting identical to the EmuSharedMem project, as I was not sure how to create a proper DLL. On Unix, you also make a new directory and copy in the makefile and makefile.common files from EmuSharedMem, that you adapt to your library (rename EmuSharedMem to Hero in my case).
You then need one hero_Hooks.cpp file for your custom hook, and on Windows you need an additional DLLMain.cpp file. You can copy the one from EmuSharedMem, it works fine.

Here is the contents of the hero_Hooks.cpp file. It ensures the function is exported as a DLL on Windows, implements the hook signature, and makes the character a ranger !
Code:
#include "../common/debug.h"
#include "../common/eq_packet_structs.h"
#include "../common/default_Hooks.h"
#include "../common/classes.h"

#ifdef WIN32
	#define exportfunc extern "C" __declspec(dllexport)
#else
	#define exportfunc extern "C"
#endif

/** Makes all newly-created characters Rangers - It is the class chosen for heroes as it can cast spells
 *  and have dual-wield. After all, aren't all rangers heroes ?
 */
exportfunc void hero_CharacterCreation_ChangeCreationInfo(CharCreate_Struct *cc)
{	cc->class_ = RANGER;
};
CheckHookSignature(CharacterCreation, ChangeCreationInfo, hero_CharacterCreation_ChangeCreationInfo);
Note that the CheckHookSignature macro call is not mandatory, but it will warn you in case the hook signature changes (the compiler will report an error).

Then you compile, copy the Hero.[dll|so] library file with his friends, the world and zone executable in your server directory, and you run your server. Guess what, nothing has changed (yet).

You need to tell the emulator that you want to use this new hook for your ruleset. If you have never played with rules before what's coming next will be rough, but I will not try to explain how rules work. You can certainly find this information on the site.

Run the following commands against your database to enable the new hook :
Code:
ALTER TABLE rule_values MODIFY rule_value VARCHAR(128);

INSERT INTO rule_sets values ('2', 'hero');

INSERT INTO rule_values VALUES ('2','CharacterCreation:ChangeCreationInfo','Hero:hero_CharacterCreation_ChangeCreationInfo');

INSERT INTO variables(varname, value, information) VALUES ('RuleSet', 'hero', 'Rule set currently in use for this server');
Note that it will alter your database to allow for long rule values. You could very well stay with the old rule values column size, but you will be forced to use very short library/function names, so that the value can fit in the column. Yes, that means 9 characters total for the library plus the function name (the column is size 10, and you have to include a colon in there). If you do not want to alter your database, rename the function something like "h001", and use "Hero:h001" for the rule value in the query above. It should work fine.

You need to restart (or start) your world server for the rule to be re-read from the database. Once your world server is up, fire up the EQ client and create a new character, preferably not a ranger. You will get a ranger anyway, even if your race does not allow it.

I hope you like rangers
Reply With Quote