Go Back   EQEmulator Home > EQEmulator Forums > Development > Development: Custom Code

Development: Custom Code This is for code thatdoes not emulate live and wont be added to the official code.

Reply
 
Thread Tools Display Modes
  #1  
Old 09-24-2014, 12:00 AM
zerjz3
Banned
 
Join Date: Aug 2010
Location: Sanctuary
Posts: 269
Default Changing the level-based class prefixes in /who

My goal is to change this part of classes.cpp:

Code:
const char* GetEQClassName(uint8 class_, uint8 level) {
	switch(class_) {
		case WARRIOR:
			if (level >= 70)
				return "Vanquisher";
			else if (level >= 65)
				return "Overlord"; //Baron-Sprite: LEAVE MY CLASSES ALONE.
			else if (level >= 60)
				return "Warlord";
			else if (level >= 55)
				return "Myrmidon";
			else if (level >= 51)
				return "Champion";
			else
				return "Warrior";
to something that checks for the player either having a certain flag, or having a certain item in their inventory. Is this at all possible?
Reply With Quote
  #2  
Old 09-24-2014, 01:41 AM
Drajor's Avatar
Drajor
Developer
 
Join Date: Nov 2012
Location: Halas
Posts: 355
Default

The client decides what text to print based on a class number in the who response. Name and Guild name are the only server-side changeable fields I am aware of. You could try messing with the rankmessage field (Gives GM/Trader additional text in who results). Worth playing around with for sure!
__________________
Drajor regards you indifferently -- what would you like your tombstone to say?
Reply With Quote
  #3  
Old 09-24-2014, 02:05 AM
jdoran
Hill Giant
 
Join Date: Jul 2012
Posts: 212
Default

Edit: Drajor posted while I was writing the following. I didn't know that /who was done client-side. But perhaps zerjz3 wanted to change that function for some other reason? I'm reaching.

You would need to change the if statements to something more complicated. The problem is that GetEQClassName() currently depends only on class and level. You would need to add another parameter to the function.

Now the easiest way to do this is place the new parameter at the end, and assign a default value. However... GetEQClassName already has an optional parameter: level. You could require a level be passed everywhere you want the new titles, or for about the same amount of work you could just pass in a new parameter. A pointer to a Client would seem a reasonable choice.

That isn't such a tough problem. We can (under Linux) use find and grep to search for usage. Visual Studio can do the same thing under Windows. Now while there are advanced regular expressions in grep, I'm lazy and like to stick with the simple stuff. So, in your eqemu directory:

find . -exec grep GetEQClassName {} /dev/null \; 2> /dev/null | grep -v Binary

give us:

Code:
./common/classes.h:const char* GetEQClassName(uint8 class_, uint8 level = 0);
./common/classes.cpp:const char* GetEQClassName(uint8 class_, uint8 level) {
./zone/embparser.cpp:           ExportVar(package_name.c_str(), "class", GetEQClassName(mob->GetClass()));
./zone/client.cpp:      Message(0,"Your target is a level %i %s. It appears %s and %s for its level. It seems %s",who->GetLevel(),GetEQClassName(who->GetClass(),1),dmg,hitpoints,resists);
./zone/bot.cpp:         GetBotOwner()->Message(15, "A %s - %s bot was detected. Is this Race/Class combination allowed?.", GetRaceName(GetRace()), GetEQClassName(GetClass(), GetLevel()));
./world/client.cpp:     clog(WORLD__CLIENT,"Name approval request. Name=%s, race=%s, class=%s",char_name,GetRaceName(race),GetEQClassName(clas));
./world/clientlist.cpp:                                 sprintf(line, "  %s[RolePlay %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetEQClassName(cle->class_(),cle->level()), cle->name(), GetRaceName(cle->race()), tmpguild, tmpZone, LFG, accinfo);
./world/clientlist.cpp:                                 sprintf(line, "  %s[ANON %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetEQClassName(cle->class_(),cle->level()), cle->name(), GetRaceName(cle->race()), tmpguild, tmpZone, LFG, accinfo);
./world/clientlist.cpp:                         sprintf(line, "  %s[%i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetEQClassName(cle->class_(),cle->level()), cle->name(), GetRaceName(cle->race()), tmpguild, tmpZone, LFG, accinfo);
./world/eqw.cpp:        res["class"] = GetEQClassName(cle->class_());
There are 7 calls to this function. Easily fixed. If you don't have a pointer to the Client handy, pass in a NULL and revert to the default behavior. It is late, and this is off the top of my head:

Code:
if ((level >= 70) 
{
    if ((client) && (client -> GetInv().HasItem(itemID, 0, 0xff)))
    {
            return "UberWarlord";
    }
    else
    {
            return "Warlord";
    }
}
Reply With Quote
  #4  
Old 09-24-2014, 02:06 AM
Drajor's Avatar
Drajor
Developer
 
Join Date: Nov 2012
Location: Halas
Posts: 355
Default

I just tested this quickly, you can use strings from eqstr_us.txt for rank.
My level 1 cleric was listed as;
High Priest[1 Cleric] Daaxodush (Human).

Pretty neat.
__________________
Drajor regards you indifferently -- what would you like your tombstone to say?
Reply With Quote
  #5  
Old 09-24-2014, 07:13 AM
zerjz3
Banned
 
Join Date: Aug 2010
Location: Sanctuary
Posts: 269
Default

Quote:
Originally Posted by Drajor View Post
I just tested this quickly, you can use strings from eqstr_us.txt for rank.
My level 1 cleric was listed as;
High Priest[1 Cleric] Daaxodush (Human).

Pretty neat.
How exactly did you go about this? I know that the names of the ranks can be edited in eqstr_us.txt , but if I wanted to have two available rank titles for each class, how would I execute this?

Did you use the method written out by jdoran to do this or did you simply edit something in eqstr_us.txt? I tried adding this code

Code:
if ((level >= 70) 
{
    if ((client) && (client -> GetInv().HasItem(itemID, 0, 0xff)))
    {
            return "UberWarlord";
    }
    else
    {
            return "Warlord";
    }
}
to classes.cpp and compiling, but there were many errors when trying to compile.

Looking for just a little more hand holding here, as I think it seems like this is possible based on what you guys are saying, but just not exactly sure how to execute it yet.


Edit: These are the three errors I get when trying to compile:

Code:
Error	1	error C2065: 'client' : undeclared identifier	C:\EQ\Source\common\classes.cpp	24	1	common
Error	2	error C2227: left of '->GetInv' must point to class/struct/union/generic type	C:\EQ\Source\common\classes.cpp	24	1	common
Error	3	error C2228: left of '.HasItem' must have class/struct/union	C:\EQ\Source\common\classes.cpp	24	1	common
Reply With Quote
  #6  
Old 09-24-2014, 07:39 AM
Drajor's Avatar
Drajor
Developer
 
Join Date: Nov 2012
Location: Halas
Posts: 355
Default

Quote:
Did you use the method written out by jdoran to do this or did you simply edit something in eqstr_us.txt? I tried adding this code
Neither. See EntityList::zoneWho, specifically;
Code:
if (ClientEntry->IsTrader())
	WAPP2->RankMSGID = 12315;
else if (ClientEntry->IsBuyer())
	WAPP2->RankMSGID = 6056;
else if (ClientEntry->Admin() >= 10)
	WAPP2->RankMSGID = 12312;
else
	WAPP2->RankMSGID = 0xFFFFFFFF;
The RankMSGID corresponds to a string ID from eqstr_us.txt. You could add more conditions there for detecting an item or whatever. If you check the hard coded IDs currently in use you find;

12315 TRADER
6056 BUYER
12312 * GM *

Based on my limited tests you can use any valid string ID. Note that this only applies to local zone who, not who all which happens in different place.
__________________
Drajor regards you indifferently -- what would you like your tombstone to say?
Reply With Quote
  #7  
Old 09-24-2014, 07:59 AM
zerjz3
Banned
 
Join Date: Aug 2010
Location: Sanctuary
Posts: 269
Default

Awesome, drajor! I've got this working in its natural form. Now, I just need to find the condition to check if a player has an item. I could actually really use an example of that if you don't mind helping me out just a bit more. I've searched around but everything I've found deals with checking items in quest scripts but not in the source code
Reply With Quote
  #8  
Old 09-24-2014, 08:20 AM
Drajor's Avatar
Drajor
Developer
 
Join Date: Nov 2012
Location: Halas
Posts: 355
Default

Quick and nasty;
Code:
if (ClientEntry->IsTrader())
	WAPP2->RankMSGID = 12315;
else if (ClientEntry->IsBuyer())
	WAPP2->RankMSGID = 6056;
else if (ClientEntry->Admin() >= 10)
	WAPP2->RankMSGID = 12312;
else if (ClientEntry->GetInv()->HasItem(20542) > -1)
	WAPP2->RankMSGID = 8043;
else
	WAPP2->RankMSGID = 0xFFFFFFFF;
This (should) check whether that character has item 20542(Singing Short Sword) and change their /who output to have Lyricist prefix.. e.g.

Lyricist[1 Bard] Drajor (Barbarian)
__________________
Drajor regards you indifferently -- what would you like your tombstone to say?
Reply With Quote
  #9  
Old 09-24-2014, 08:25 AM
zerjz3
Banned
 
Join Date: Aug 2010
Location: Sanctuary
Posts: 269
Default

Code:
Error	10	error C2819: type 'Inventory' does not have an overloaded member 'operator ->'	C:\EQ\Source\zone\entity.cpp	4076	1	zone
Error	11	error C2232: '->Inventory::HasItem' : left operand has 'class' type, use '.'	C:\EQ\Source\zone\entity.cpp	4076	1	zone
I get these errors when compiling with that code... seems like we're getting really close to having this figured out.. I copy/pasted what you posted, checking now to make sure I didn't leave some ; or something out from being sloppy

Edit:
Code:
            else if (ClientEntry->GetInv().HasItem(17181, 0, 0xff))
	            WAPP2->RankMSGID = 8043;
compiled successfully, testing now...

Edit: Everything compiles successfully, the server runs without error, but having the specified item doesn't return any sort of string before the level and class in /who ... experimenting more with this
Reply With Quote
  #10  
Old 09-24-2014, 08:51 AM
zerjz3
Banned
 
Join Date: Aug 2010
Location: Sanctuary
Posts: 269
Default

Writing it as such

Code:
            else if (ClientEntry->GetInv().HasItem(17181) > -1)
	            WAPP2->RankMSGID = 1504;
compiles but doesn't show anything in-game.
Reply With Quote
  #11  
Old 09-24-2014, 09:00 AM
Drajor's Avatar
Drajor
Developer
 
Join Date: Nov 2012
Location: Halas
Posts: 355
Default

What client are you using?
__________________
Drajor regards you indifferently -- what would you like your tombstone to say?
Reply With Quote
  #12  
Old 09-24-2014, 09:03 AM
zerjz3
Banned
 
Join Date: Aug 2010
Location: Sanctuary
Posts: 269
Default

Quote:
Originally Posted by Drajor View Post
What client are you using?


I'm on the Titanium client... only client I have atm
Reply With Quote
  #13  
Old 09-24-2014, 09:10 AM
Drajor's Avatar
Drajor
Developer
 
Join Date: Nov 2012
Location: Halas
Posts: 355
Default

I am fairly certain that anything below SoF handles /who client side :( I recommend Underfoot for everything except P99.
__________________
Drajor regards you indifferently -- what would you like your tombstone to say?
Reply With Quote
  #14  
Old 09-24-2014, 09:11 AM
zerjz3
Banned
 
Join Date: Aug 2010
Location: Sanctuary
Posts: 269
Default

Ok, I will get a copy of Underfoot and report back in this thread with my findings.
Reply With Quote
  #15  
Old 10-13-2014, 04:15 PM
zerjz3
Banned
 
Join Date: Aug 2010
Location: Sanctuary
Posts: 269
Default

Update: I can confirm now with the Underfoot client that this method works for the intended purpose. Thanks for the help!
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 03:48 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3