EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Development (https://www.eqemulator.org/forums/forumdisplay.php?f=590)
-   -   Mercenaries (https://www.eqemulator.org/forums/showthread.php?t=35147)

bad_captain 10-24-2012 11:12 PM

I don't think so. The only thing I've found that can change the amount is if you use a mercenary contract instead of purchasing from one of the merchants. The mercenary contract ones are a little cheaper (maybe 2/3 the regular price) for upkeep. There is no purchase price.

I think I just had a duh! moment. When spawned, the client requests the merc data, and the server responds, which includes the purchase price as well as the upkeep cost. The server just needs to tell the client to deduct the upkeep cost. Only issue is if the client levels after the data is sent, then the cost would be greater. I would assume (haven't found evidence in my logs yet, though) that the server would resend the merc data to include the updated costs, since the client is charged the correct amount after leveling. I guess I'll need to do more searching.

Devincean 10-24-2012 11:17 PM

hey bad_captain was this pre level 50 or post because I know mercs are free no upkeep cost up to a certain level as long as its a Tier 1 or 2 merc

actually just read merc will start costing you 2g every 15 minutes at level 14. so guess the better question is were you 14+

bad_captain 10-25-2012 12:52 AM

I was around level 20. I was charged 1 plat, 9 gold. I received the message that I was charged, then I said 'upkeep' so I knew where to look. One packet may be the message that I was being charged, but that may be handled client side. I guess I just need to get back in there and get a bunch more packet collects.

Noport 10-25-2012 06:25 AM

Code:

OP_ClientUpdate=0x7062            #
OP_MoneyUpdate=0x528f                  #
OP_MercenaryDataResponse=0x6537          #
OP_CommonMessage=0x2e79            # You have been Charged for Upkeep

Opcode 0x6537 looks like your 12min timer was rest the opcode converted from hex to dec in ms time
2D65 hex converted to dec 11621 ms timer

chrsschb 10-25-2012 08:43 AM

I like the idea of being able to control their stats per level / tier in a table like current NPCs, but using that method how would you scale stats for say Level 60 players who are going from Kunark to Velious and eventually into SoL. The level cap stayed 60 that entire time but the content got exponentially harder.

The tier system wouldn't work for this because once a tier is unlocked it's always unlocked. The progression of merc power needs to work similar to the players and not eventually permanently pass the player (especially not by a significant margin like current Live mercs).

bad_captain 10-25-2012 01:55 PM

Being able to give mercs equipment would help with that, but I think even if mercs have equipment, allowing equipment trades would be a low priority.

I'm more concerned about having to have a record for every level for mercs, for each proficiency, for each tier, for each class. That would be 4 classes, 3 proficiencies including master, 5 tiers, and however many levels each server allows.

Maybe there can just be a tier modifier for each proficiency, with records for certain level ranges. I.E for levels 1-50, you have one record with stats that would max at level 50. In the code, it would scale the stats based on level. Then, another record for lvls 51-65, and so on. That way you could scale based on level, while giving the opportunity to change some parameters at certain levels.

I currently have skills being set to the max for their level based on their class, but I guess that could be put in the database as well.

trevius 10-26-2012 02:38 AM

I think skills being max for their level is fine. It wouldn't hurt to have the option to be able to set it in the DB, but that shouldn't be something to really worry about at this point.

I think the best way to handle stats would probably just be to do it the long way by having each merc class/proficiency/level in the DB. Even for a server with max level of 80, that is only like 960 entries, which isn't huge in terms of db entries. Most of that could be written, adjusted, and scaled by simple queries fairly quickly using similar formulas to what might be used if we had scaling hard set in the source.

I am sure it could be done by setting a base and then having fields for scaling each field by X amount for levels Y+ or whatever, but having the individual entries allows for the most flexibility by far and shouldn't be too hard to manage.

As far as the upkeep cost packets go, the first one was definitely just an OP_MoneyUpdate, which I broke down here:

Code:

12/8/2011 9:02:45 PM
[OPCode: 0x528f] OP_Unknown [Server->Client] [Size: 16]
2d 00 00 00 - 45 Platinum
00 00 00 00 - 0 Gold
06 00 00 00 - 6 Silver
05 00 00 00 - 5 Copper

OP_MoneyUpdate

struct MoneyUpdate_Struct{
        sint32 platinum;
        sint32 gold;
        sint32 silver;
        sint32 copper;
};

My guess is that the 45 Plat and change is how much you had on your char after the charge happened. You probably started with 46 Plat 9 gold 6 silver and 5 copper, or something like that before the charge.

So, the charging for mercs should be very simple and is no different than how we already do money updates for just about everything else.

I am not 100% sure about the second packet. Your collect is from a time-frame that I don't have a good opcode reference for, so without the full collect and other merc packet examples, I am not able to verify for sure which packet that is. Since it is 4 bytes and is definitely around the merc related opcodes, I assume it is what we currently refer to as OP_MercenaryHire.

Code:

// [OPCode: 0x5e78 (OP_MercenaryHire?)] On Live as of April 2 2012
// Sent by Server in response to requesting to view Mercenary info or Hire a Mercenary
struct MercenaryMerchantResponse_Struct {
/*0000*/ int32 ResponseType; // Seen 0 for hire response, 6 for info response, and 9 for denied hire request
/*0004*/
};

My guess is that ResponseType 10 is just a server response saying you get to keep your merc :) If that is the case, then there is probably another ResponseType for dismissing mercs as well, but we will need to figure out what that is either via collects or by testing with sending different ResponseTypes from 0 to 10 (or so). It could also be that there is a separate packet/opcode for dealing with dismisses or whatever that upkeep packet is, but I would need a more complete collect example to be able to tell for sure.

sorvani 10-26-2012 09:43 AM

Quote:

Originally Posted by chrsschb (Post 213625)
I like the idea of being able to control their stats per level / tier in a table like current NPCs, but using that method how would you scale stats for say Level 60 players who are going from Kunark to Velious and eventually into SoL. The level cap stayed 60 that entire time but the content got exponentially harder.

The tier system wouldn't work for this because once a tier is unlocked it's always unlocked. The progression of merc power needs to work similar to the players and not eventually permanently pass the player (especially not by a significant margin like current Live mercs).

While that would be a nice concept to implement for custom servers, that is not how mercs work on live. It is more important to make sure the design will make them work as they do on live, and then keep/add room for customization where possible for non-legit servers.

chrsschb 10-26-2012 10:42 AM

Quote:

Originally Posted by sorvani (Post 213647)
While that would be a nice concept to implement for custom servers, that is not how mercs work on live. It is more important to make sure the design will make them work as they do on live, and then keep/add room for customization where possible for non-legit servers.

Which is exactly what I was trying to convey (even if it didn't come out that way). Thanks.

bad_captain 10-26-2012 01:01 PM

I completely forgot about the money update packet and how it works. I'll see if I can get that MercHire packet to work. I think you are correct, since when upkeep is charged, a check is made to make sure there is enough money to keep the merc. Otherwise, the merc is dismissed. It also sends the message that you have been charged upkeep, but I wasn't sure if it was just a message packet or not.

For stats, I can see a benefit both ways. If rules were used, it would be much simpler to modify stats off of a few base merc records (still have per level, class, at least, probably proficiency as well.). But, you missed tier, so multiply that total by 5. Besides HP, Mana and Maxhit(if used), I'm not sure many stats will have that big of an impact, at least less than skill or spells and their focuses.

I guess for now I'll leave stats how I have them so I can work on other things. I just have base stats, then item, spell, and aa bonuses (which we could rename merc bonuses and would be based on proficiency and tier) . Then we can set the base stats to whatever we decide. I am under the assumption we will be using max and min hits instead of calculating them from weapons. This way, some combat code can be worked on.

trevius 10-29-2012 03:34 AM

FYI, I haven't given up on doing Merc work. I am just taking a bit of a break before working on more of it. I started reading this "Thinking in C++" book to give me a better understanding of coding before picking back up on it. About halfway done with the book so far. It is a good learning experience and is filling in details for stuff I am familiar with from reading the source, but never really fully understood in depth. Up to this point, almost everything I have learned about coding has been from examples in the EQEmu source. So, it will be nice to understand everything a bit better before picking up on more coding (about time, right?) :)

Hopefully I can finish the book up this week and start back into working on more stuff. The winter is normally a good time for coding anyway, since there are less things to do outside and around the house so there is more free-time for dev work.

joligario 10-29-2012 07:35 AM

By Bruce Eckel?

trevius 10-29-2012 07:49 AM

Quote:

Originally Posted by joligario (Post 213785)
By Bruce Eckel?

Yep, that is the one. Seems pretty good so far for a free one. It assumes the reader is a C programmer, so it isn't really for beginners or anything, but it covers stuff pretty well either way if you have the basic idea of what is going on. Sorry, not trying to derail this thread :)

bad_captain 11-01-2012 12:48 AM

I just committed some work I've done on mercs. Suspend is mostly working, basic stats are in (#showstats shows the stats we give the merc).

I had the 15 minute timer working at one point, but broke it again, so I need to figure out what happened with that. When the timer was working, I was being charged the upkeep, although the message stating the amount charged was incorrect.

I believe that suspend mostly works, but am unable to test unsuspend, because for some reason, no matter what I send in for suspended time in the suspend response packet, I get either 0 time remaining or 400+ hrs remaining. I'm not going to wait that long. There may be a mixup somewhere with the opcodes, because I get the following message:

Code:

[11.01. - 00:01:12] [WORLD__CLIENT_ERR] bad_captain: Received unknown EQApplicationPacket
[11.01. - 00:01:12] [WORLD__CLIENT_ERR] [OpCode OP_MercenaryTimerRequest (0x0924) Size=1]
[11.01. - 00:01:12] [WORLD__CLIENT_ERR] 0000: 30

I don't think the timer is being handled correctly, if at all. I don't get the

Code:

Message(7, "Mercenary Debug: Timer Request received.");
message at all, even when I got the 15 minute timer to work.

Another message I get is:

Code:

[11.01. - 00:01:18] [WORLD__CLIENT_ERR] bad_captain: Received unknown EQApplicationPacket
[11.01. - 00:01:18] [WORLD__CLIENT_ERR] [OpCode OP_Unknown (0x3401) Size=0]

I'm not sure if that is a relevant opcode or not. I'm using SoD.

Anyway, I just wanted to get the work out there, and hope to look further into the issues I'm having.


Somewhat unrelated, but affecting my debugging of some of these issues, is my inability to get EqExtractor to work for me. It works for captures I did at the end of last year using SoD, as well as ones I did earlier this year on live (in Feb). Now, any capture I do says it is an unsupported client version. I also get an error on the OP_DzChooseZone opcode, as it had a total length of 5, instead of six. I'm wondering if my SoD.conf file is messed up, but even using the default one from the trunk causes the issue. If anyone has any advice, I'd appreciate it. It would certainly help me figure out what's happening with some of these packets being sent and received.

trevius 11-01-2012 03:22 AM

Yeah, I noticed the 1 byte sized packet for Dismiss on SoD and UF as well, but in my collects from VoA, they are 0 bytes. I am guessing that the case is the same for the Timer Request packet, assuming that is what the packet is for. I am not 100% sure the opcodes are correct for those on SoD and UF compared to what I have for VoA, but the order looks correct as far as I can tell so it should be.

I think we could probably just change the size check to see if it is > 1 instead of != 0 for the Timer Request, which is what I set already for the dismiss request. I have no idea what the 30 (48 in decimal) means, but that is the same thing I was seeing in the dismiss packets in SoD and UF. It may be that the client is sending that because of some mistake elsewhere in the data we are sending in other packets, but that is just a guess at best.

The Unknown 0x3401 opcode is most likely not merc related. I don't see the equivalent opcode being sent in my merc collects for VoA. Also, it is near most of the earlier opcodes, and merc opcodes are much later and all near each other in the order, so it is probably for something else like deleting spawns or something.

Maybe I can get some time to mess with the suspend timer stuff and see if I can get that working.

I haven't messed with the code for it at all yet, but I could probably look into getting the extractor working for Live, and maybe SoD if that is an issue and is needed. Unfortunately, I kinda suck at reading packets that haven't been dumped, cause I don't know the packet header stuff too well yet. I am sure I could figure it out though. I think the collector only requires a minimum amount of correct opcodes and structures to function, so it shouldn't be too hard to get that working. I think one of the main things is to make sure the PP packet struct is correct size. I really don't know why it would error out on any DZ packet sizes, as that seems to be completely irrelevant to identifying client version unless Derision changed the extractor to use that packet for identifying the client instead of the one we use for EQEmu. It would probably take a bit for me to familiarize myself with the code for the extractor, but it would be good stuff to know anyway. I am sure Derision would appreciate help with maintaining it so he isn't the only one doing it.

Noport 11-01-2012 04:16 AM

you can get cavedude precompiled Version here https://code.google.com/p/projecteqd...e.zip&can=2&q=

says it is an unsupported client version:
keep your opcode files in format of patch_Oct16-2012.Conf
make sure you have a file with the same name as patch_oct16-2012.CS in the same directory.
so you might have to copy and rename *.cs files to match your *.conf file name
if you keep having the same problem download wireshark Version 1.8.2

that is the reason you are receiving unspported client version.

Code:

OP_DzChooseZone=0x3c5b                 

# Mercenary Opcodes:
OP_MercenaryList=0x195c        # 0x5a0a
OP_MercenaryHire=0x4dd9                       
OP_MercenaryDismiss=0x0bd0             
OP_MercenaryTimer=0x2ef8                       
OP_MercenaryTimerRequest=0x0924       
OP_MercenaryCommand=0x6c36               
OP_MercenaryDataUpdate=0x57f2               
OP_MercenaryDataUpdateRequest=0x05f1       
OP_MercenaryDataRequest=0x0327               
OP_MercenaryDataResponse=0x6537               
OP_MercenarySuspendRequest=0x3c58       
OP_MercenarySuspendResponse=0x4b82

0x3401 was Op_NewZone in VoA it was changed in Oct 2012
OP_NewZone=0x0d60 # 0x3401

Noport 11-01-2012 06:24 AM

I have no idea what the 30 (48 in decimal) means:
30 means End if satement or else sub, or if clause
48 means EOF means end of file.

bad_captain 11-01-2012 11:40 AM

For eqextractor, I think it only needs the size of the pp. I don't think it ever gets there, maybe because of the other issue. When it checks the opcodes, it converts the opcodes to number, with playerprofile being like 245 or whatever. It loops through the opcodes to convert and at that point, it errors because of the Dz opcode. If I make the length 6 by adding a zero at the end (length is the number of characters in the opcode, not packet size. i.e. it's 0x0d6 instead of 0x0d60), it loads, but still doesn't find the correct sized pp. I added a conditional breakpoint to stop when it reached 245 or whatever the player profile one is and it never stopped. I might just use 0x0000 for the one it errors on in case the incorrect opcode causes some other error, then step through manually until I reach the player profile and see why it's not matching the size. It's just strange that it works correctly for collects from last year, but not now. Maybe something is messing up my packets. Who knows.

I'll try the size 1 timer packet and see if that helps.

For the suspend response packet, if I send the time suspended using timer::getcurrenttime, I get 400+ hrs remaining. If I send 30000 (5 minutes), I get the same. If I send the current time + 5 minutes ( in case it's actually when they are available to be unsuspended), I get 0 min 0 sec remaining. This one has me confused for sure. I haven't checked the encoding yet. Maybe there's something there.

trevius 11-05-2012 05:04 AM

Quote:

Originally Posted by bad_captain (Post 213895)
This one has me confused for sure. I haven't checked the encoding yet. Maybe there's something there.

Right now, the only encoding is for OP_MercenaryDataResponse and OP_MercenaryDataUpdate. The rest of the packets seem to not need encodes/decodes so far to my knowledge. There may need to be more encodes/decodes added, but most of the other packets are pretty small and simple, so it is less likely they will need them. It is hard for me to tell for sure without good collects from Live for each client.

Secrets 11-05-2012 09:10 AM

It's a UNIX timestamp that it uses for mercenary timers. I'm not sure what value Timer::GetCurrentTime returns, but time_t's value should work fine.

PS: I'll be helping with mercenaries soon. I had a lot of experience with the packets before I went crazy. I also have been reverse engineering other games' file formats so I learned a LOT about IDA and game design in general as a result.

I have to get my development environment set up again. Been a while.

trevius 11-05-2012 10:06 AM

Quote:

Originally Posted by Secrets (Post 213985)
before I went crazy.

I though you were born crazy! <3 Secrets :)

And yeah, it is a unix timestamp. I didn't look much into that function when I stuck that in there. I was just populating fields with data. You may be right that it is returning an undesired result.

Secrets 11-05-2012 10:11 AM

Quote:

Originally Posted by trevius (Post 213986)
I though you were born crazy! <3 Secrets :)

And yeah, it is a unix timestamp. I didn't look much into that function when I stuck that in there. I was just populating fields with data. You may be right that it is returning an undesired result.

I'll be committing what I learned from the disassembly soon.

In the meantime, here's a list of valid merc status update IDs. The packet is used on the client and server, whereas the client sends different data than the server packet. It's not just used for hiring as you can see below:

// [OPCode: 0x5e78 (OP_MercenaryHire?)] On Live as of April 2 2012
/*
Valid response IDs:

0 - Hire me! (Assign Merc after sending this.)
1 - Insufficient money message.
2 - Mercenary-To-Hire does not exist in the server's DB.
3 - Mercenary failed to spawn. (this actually tells us the mercenary should spawn BEFORE recieving this packet.)
4 - Mercenaries not allowed in raids.
5 - You already have a mercenary request pending
6 - You must dismiss the mercenary before hiring a new one.
7 - You must dismiss your suspended one before hiring a new one.
8 - Group is full.
9 - Error creating mercenary
10 - Replacing mercenary(?!)
11 - Your mercenary has quit! You ran out of money to pay for your mercenary!
12 - Your mercenary waived an upkeep cost of %d plat, and %d gold and your mercenary upkeep cost timer has been reset to %s. <-- these values are for GM resets of mercenaries and are generated from the client's
mercenary info. NOT from the packet.
13 - Your mercenary is about to be quit due to insufficient funds! <--- Sent before the mercenary quits, unsure of time sent before.
14 - There is no mercenary liason nearby! <-- hacking attempt check if no mercenary merchant is in the zone!
15 - You are too far away from the liason! <-- Liason exists as type in the zone, but client is too far away. (position update happened)
16 - You do not meet the requirements for that mercenary! <-- For example, if a mercenary is 'unlocked' in some way, send this if they do not have the mercenary unlock.
*/

Secrets 11-05-2012 11:10 AM

So, the assign packet.

It's actually a 16-byte packet that does different things depending on variable size.

I had a screenshot from when I last worked on it. Basically, there's a few fields, and you were right about the unhire struct being the same as the assign struct:
Quote:


struct MercenaryAssign_Struct {
/*0000*/ int32 MercEntityID; // Seen 0 (no merc spawned) or 615843841 and 22779137
/*0004*/ int32 MercState; // Seen 0 with no merc hired
/*0008*/ int32 MercSuspended; // Seen 1 when no merc is hired - ID unique to each type of mercenary
/*0012*/ int32 MercTimeRemaining; //UNIX Timestamp. The reason the client accepts this part of the packet missing is because SOE stupidly left no size checks. //I assume they wanted it in another packet but never removed it?
/*0016*/
};
I'm not actually sure if MercSuspended is the suspend state of the merc, it could be a list of stances from the client. It might not be. I'm not sure, I haven't observed the packet.

It's also possible the suspended state is a value from 0-4 depending on if the merc is suspended, active, dismissed or two other states? not sure.

Another thing it could be is that I have the initial hire packet and the assign packet screwed up, which would explain the merctimeremaining part being missing.

I forget what values these were but it *was* working at some point:

http://i.imgur.com/B6s0C.jpg

bad_captain 11-05-2012 11:55 PM

I did some debugging on the timer stuff. 0 or 1 sized didn't seem to help. I did notice that at some point it was working and tried to figure out how I did it.

I found out there is a bug where if you have a merc suspended, it allows you to purchase a new merc. That part is easily fixed, but I found out something interesting. If I suspend my merc, then purchase a new one, my timer suddenly began to work. With the help of the debug messages, I found that if I had a merc suspended (the client thinks I have one), and purchase a new one, it doesn't do a data request for the merc data, since I assume the client thinks it already knows it. Somewhere in the data response, where it requests the current merc (merchant ID = 0), there's something that causes the timer to not work.

I did notice that there are two very similar structures: MercenaryData_Struct and MercenaryListEntry_Struct. There may be a chance to combine the two, and there may be a mixup of when to use one or the other, or something. I'll check into this a little more, but I thought I would throw it out there.

trevius 11-06-2012 04:34 AM

Thanks for the info, Secrets! That is some nice data for the hire packets for sure.

Quote:

Originally Posted by bad_captain (Post 214013)
I did notice that there are two very similar structures: MercenaryData_Struct and MercenaryListEntry_Struct. There may be a chance to combine the two, and there may be a mixup of when to use one or the other, or something. I'll check into this a little more, but I thought I would throw it out there.

Yeah, when I first wrote the structs, those 2 were using the same struct for their packets. The problem was that on the Live collect from VoA that I have, the MercenaryData_Struct has an extra field at the end, which I am really not too sure about. So, I split them up into 2 separate structs just to get things working. Since we actually build those packets on the fly in the patch files, the structs don't actually matter other than being a place to store the data so we can pull it when creating the packets in the path files. So, at this point, we should be able to just remove the MercenaryListEntry_Struct struct and store everything in MercenaryData_Struct instead, including the additional field. Even if that additional field isn't used, we can determine if we want to use it or not when we create the packets in the patch files.

Right now, it looks like I have that additional field at the end of the data update commented out in the encodes. I would either need a collect from SoD and UF or to have someone like Secrets to check the IDA output to figure out the correct packet struct to verify if it is correct or not. Maybe just uncommenting that so it adds the extra field would make it work, I dunno. I also don't know if that field only comes at the end of the packet, or if it can also come with every iteration of the merc data if more than one merc is owned. If it is related to owning multiple mercs, I think that was added later, so SoD and maybe UF might not have that field. At this point, it is just speculation though.

It is interesting that your timer started working when you had a merc already suspended. That sounds like the client is ignoring the merc data update response the way we are sending it. Something like that could definitely be caused by a packet struct issue, like size, which could be due to that missing field at the end (or any other peice of data). Right now, the data update struct isn't being fully populated based on what I saw on my VoA collects anyway. I know the merc name field is not yet being populated, which could also be the reason why it is failing. The variable sized packets just take a bit more work to get them sending as needed, but I am sure we can work out the rest of whatever is needed easy enough. The merc name field can probably just be changed to be 64 bytes, and we can add that to the encode with the appropriate size and null terminator. Also, if that last field in the data update only comes after the iterations for each merc data, we can't add it after "MercenaryData_Struct MercData[0]" due to the fact that 0 sized arrays have to be at the end of the struct, but we could easily just add it in during the encode by checking if we are on the last iteration and only adding it then. Either way, that doesn't matter too much at this point, until we get to the point of trying to manage more than 1 owned merc at a time.

bad_captain 11-06-2012 11:35 AM

The ability to have multiple mercs came in December of last year, which was a month after VoA came out. From the December 14th 2011 patch notes:

Quote:

Mercenary Roster -
- Players can now buy extra mercenary slots on the Marketplace and keep a roster of mercenaries that they can switch between. Mercenaries operate the way they used to, except that if you purchase another mercenary, it will become active and replace the mercenary you had active before (if any). Dismissing a mercenary will cause the first remaining mercenary in your roster to become the active mercenary (though suspended). Transferring a mercenary will cause the target player's active mercenary to be suspended and the newly transferred one to become active.
- To switch mercenaries in your roster, open the Mercenary Management UI.
- Added the new command /mercswitch. With no arguments, it lists the current roster of mercenaries and displays the one that is currently active. Adding a parameter allows switching between mercenaries in the roster.
I don't think the name is needed for SoD or UF, and wasn't present until this patch. I have collects from December 7th or 8th (before the change), and then Provocating sent me caps from December 27th - 30th (after). One of the unknowns may not be needed as well, I will have to double check my packets to verify. The additional fiend at the end may have come at the same time, as I don't believe it is in my captures either. I hope to verify tonight, but things have been a little busy around work with the election.

Here's a packet from 12/5:

Code:

12/5/2011 2:56:56 AM
[OPCode: 0x0327] OP_MercenaryDataResponse [Server->Client] [Size: 82]
000 | 01 00 00 00 e4 a4 bf 07 01 00 00 00 16 07 00 00  | ................
016 | e4 a4 bf 07 29 41 c0 07 00 00 00 00 00 00 00 00  | ....)A..........
032 | 00 00 00 00 00 00 00 00 13 00 00 00 00 a0 bb 0d  | ................
048 | 00 24 00 00 00 01 00 00 00 02 00 00 00 00 00 00  | .$..............
064 | 00 01 01 00 00 00 02 00 00 00 00 00 00 00 01 00  | ................
080 | 00 00                                            | ..

The Group UpdateB packet and the two following have the merc's name.

Code:

[OPCode: 0x7139] OP_Unknown [Server->Client] [Size: 86]
000 | e1 ad 00 00 02 00 00 00 xx xx xx xx xx xx 00 00  | ........MyName..
016 | 00 00 00 xx xx xx xx xx xx 00 00 00 00 05 00 00  | ...MyName.......
032 | 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00  | ................
048 | 44 69 61 73 72 69 72 31 30 32 37 39 39 00 01 00  | Diasrir102799...
064 | xx xx xx xx xx xx 00 05 00 00 00 00 00 00 00 00  | MyName..........
080 | 00 00 00 00 00 00                                | ......


Code:

12/5/2011 2:56:58 AM
[OPCode: 0x7706] OP_Unknown [Server->Client] [Size: 16]
000 | 5c 02 00 00 c2 04 00 00 44 69 61 73 72 69 72 00  | \.......Diasrir.

I haven't checked to see if those opcodes have been figured out. I just wanted to post them for reference.

trevius 11-06-2012 01:15 PM

I think those 2 unknowns are just normal group packets. They look pretty familiar just based on the info in them.

That 12/5/11 packet is interesting. Here is the breakdown of the packet into a struct as far as I can tell. Almost all of the fields match up with what I have seen on VoA other than the last extra field on VoA and the Status field for the new F2P membership stuff. Though, there appears to be an extra MercType field at the top of the struct, which is something I haven't seen before. Maybe if we try the struct like that, the update will work properly. I will see if I can figure out a good way to do that. I can't think of a good reason to have the MercType field redundant like that unless it is something to tell the client which is the highest type it currently has access to or something.

Code:

01 00 00 00 - 1 - MercStatus
e4 a4 bf 07 - 130000100 - MercType again ?
01 00 00 00 - 1 - MercCount
16 07 00 00 - 1814 - MercID
e4 a4 bf 07 - 130000100 - MercType
29 41 c0 07 - 130040105 - MercSubType
00 00 00 00 - 0 - PurchaseCost
00 00 00 00 - 0 - UpkeepCost
00 00 00 00 - 0 - AltCurrencyCost
00 00 00 00 - 0 - AltCurrencyUpkeep
13 00 00 00 - 19 - AltCurrencyType
00          - 0 - MercUnk01
a0 bb 0d 00 - 900000 - TimeLeft
24 00 00 00 - 36 - MerchantSlot
01 00 00 00 - 1 - MercUnk02
02 00 00 00 - 2 - StanceCount
00 00 00 00 - 0 - MercUnk03
01          - 1 - MercUnk04
01 00 00 00 - 1 - StanceIndex
02 00 00 00 - 2 - Stance
00 00 00 00 - 0 - StanceIndex
01 00 00 00 - 1 - Stance


bad_captain 11-06-2012 05:22 PM

I think it is the same as the initial data response, where it has the number of types to follow, the merc type, the number of mercs that follow, and then the merc. From what I've seen after hiring 5-10 mercs during that time ( I was mostly trying to get the full response packets so I didn't get as much as I'd like of later packets), the first is always 1, followed by the type. I may be wrong though. I guess I never did try hiring and not actually get to hire. Maybe one of the other fields is status?

And thanks for fixing my post. I was in a hurry to go vote before work and missed that.

trevius 11-07-2012 08:21 AM

Ahh, that makes more sense. I didn't even think about it that way because the struct I have from April 2 2012 shows the following structure:

Code:

[OPCode: 0x6537] OP_MercenaryDataUpdate [Server->Client] [Size: 93]

00 00 00 00 - 0 - MercStatus
01 00 00 00 - 1 - MercCount
8f 01 00 00 - 399 - MercID
e4 66 ab 13 - 330000100 - MercType
09 b5 ab 13 - 330020105 - MercSubType
bb 00 00 00 - 187 - PurchaseCost
b2 00 00 00 - 178 - UpkeepCost
01 00 00 00 - 1 - Status
00 00 00 00 - 0 - AltCurrencyCost
01 00 00 00 - 1 - AltCurrencyUpkeep
13 00 00 00 - 19 - AltCurrencyType
00          - 0 - MercUnk01
a0 bb 0d 00 - 900000 - TimeLeft
05 00 00 00 - 5 - MerchantSlot
01 00 00 00 - 1 - MercUnk02
02 00 00 00 - 2 - StanceCount
88 d5 8b c3 - 3280721288  - MercUnk03
01          - 1 - MercUnk04
4b 65 6b 6c 65 6b 00 Keklek - MercName
00 00 00 00 - 0 - StanceIndex
01 00 00 00 - 1 - Stance
01 00 00 00 - 1 - StanceIndex
02 00 00 00 - 2 - Stance
01 00 00 00 - 1 - MercUnk05

Note the additional fields I saw are in green, and MercUnk03 also has some data in it in the VoA collect, where yours looks almost just like what they do when sent as a merchant list with no data in MercUnk03.

Maybe they used to use the same structs for merchant lists and the data updates, but changed that later in VoA since some things like the MercTypes list are unneeded.

Either way, at least both versions are in this thread as examples for that packet, which may help for comparison purposes.

Secrets 11-07-2012 09:56 AM

I can confirm that the OP_MercenaryDataUpdate packet that we have listed is not existent in any packet handlers for Seeds of Destruction. Not sure about underfoot but the opcode we have listed is not there at all.

Secrets 11-09-2012 02:22 PM

http://i.imgur.com/1zlme.jpg

Secrets 11-09-2012 06:59 PM

Gonna be committing the next part of the merc stuff tonight; I got the packets in order and well, a quite nice result:

http://i.imgur.com/IjZin.jpg

trevius 11-09-2012 09:47 PM

Score! Good work :)

Secrets 11-11-2012 05:35 PM

Mercenaries are now in an implementable state! I finished the last few bits of packet work over the last few days. We now can suspend/unsuspend, have a merc charge upkeep based on a timer, and all of these features are saving cross-zone.

I also tested in on the Underfoot client and it works just as well as titanium. The only thing that doesn't work is the auto-assist button but I assume we can implement that during the AI stuff. It's a simple button setting that the client sends to the server, and the server must send it back at some point. I could look into it, but I would rather get the AI stuff working before we go implementing an auto-assist/call target function!

bad_captain or trevius, if you would like to start work on the AI with me, that would be great. Thankfully we can just copy-paste bots for the most part. I'd like to see this go live on PEQ soon, would be nice to add this to an array of features EQEmulator has. And I can't even begin to imagine the custom server possibilities.

bad_captain 11-11-2012 11:11 PM

Great work, Secrets!

I took a few days off, but planned on getting back to it. I was planning on working on the database side, for getting the basic stats per level, class, proficiency, etc., naming rules, and anything else that's still needed.

A decision that still needs to be made is whether mercs use equipment (and weapons) or max & min hit values. The benefit of using weapons would seem to be less balancing that would need to be done in the database, since there wouldn't be records that would need to be updated per level, class, proficiency, and tier. That's quite a few records to have to change if melee attacks are under or over powered. On the other hand, if weapons are used, it could require more data elements that need to be edited to change the resulting damage.

As you said, much of the AI can be copied from bots and edited where needed. I'm sure the stance code for bots can be improved, but that could provide a start. I'm still working to get all spells used, and I know they differ based on the selected stance, so that data still needs to be captured completely. I think I can currently come up with basic spell sets for all of them, but more data is needed, especially for higher levels.

Secrets 11-11-2012 11:24 PM

Fairly certain on live mercs do not use weaponry, and instead have min/max values based on level. According to a few posts on ZAM, proficiency determines how many NPCs a merc can take on at once before feeling 'overwhelmed', an overwhelmed merc will fight but with a debuff. Not sure where the debuff is from or if it's a spell or anything. Tier determines the quality (dps output) of the mercenary.

Also, from limited testing on live, mercs seem to follow NPC stat rules more than PC stat rules. With the exception of HP, their damage seems more like that of an equal level NPC. For example, a level 50 mercenary deals around 151 points of damage and quad-attacks. This is close to being on par with a Plane of Justice sentinel, but with extra quad attacks. As for HP their HP is more so that of a player. They do not follow AA rules as far as I can tell, however, they have considerably more AC than a player would at that level. They seemed easily damaged by spell casters, so I assume they have very little resists.

I think the best way to do it would be min/max anyways; weapons do not make sense as mercenaries on live do not store items.

That only covers tank mercs, caster mercs are another animal entirely but from my testing they follow PC spell rules in general but only basic functionality; ie, heals, hots, very minor buffs (no resist buffs. hp/ac only), and cures. I didn't play live when caster (ranged dps) mercs were implemented so I cannot comment on them.

Due to the 'era' of what PEQ is in, If they were added on PEQ they would severely imbalance gameplay unless tweaked. The level 68 mercenaries were doing 768 damage quad (!) and that's a bit absurd for PEQ's DPS output at the moment.

Perhaps PEQ can increase the quality of mercenaries per expansion. They should always match the quality of NPC that is in the next expansion, for general rule of thumb. This is why SOE does level cap increases with most expansions; so they can balance out mercenaries and do a gear reset.

Robregen 11-12-2012 01:15 AM

Quote:

Due to the 'era' of what PEQ is in
could probably add in an optional rule to allow mercenary or what's not.

bad_captain 11-12-2012 01:33 AM

Okay, I'll see what I can do stat-wise, and use min & max hit. Once it's in place and scaling somewhat, the attack & other combat code can be cleaned up.

For confidence, it also determines if and when a merc flees. I was 'moloing' around crushbone and had 4-5 even or higher con mobs attacking me, and had my merc high-tail it out of there. It was pretty funny.

I have spells cast by healer mercs for apprentice mercs through level 60. I will try to test on the test server with journeyman mercs for their spell lineups- it's based on stance, and journeymen have more stances available.

Once option is to have a scaling rule available where at 100 (%), merc damage output would be exactly what is listed in the database, whereas 50 (%) would be half that. That may be oversimplifying it, but I think something could be in place to easily allow server admins to adjust merc damage (and possible stats), without having to manually update thousands of records (or run a script updating all records).

sorvani 11-12-2012 02:35 AM

Quote:

Originally Posted by bad_captain (Post 214231)
Once option is to have a scaling rule available where at 100 (%), merc damage output would be exactly what is listed in the database, whereas 50 (%) would be half that. That may be oversimplifying it, but I think something could be in place to easily allow server admins to adjust merc damage (and possible stats), without having to manually update thousands of records (or run a script updating all records).

This would be the best way to handle it hands down. Most basic server admins can not do a lot of SQL and a simple rule would be perfect.

trevius 11-12-2012 03:01 AM

Quote:

Originally Posted by Robregen (Post 214230)
could probably add in an optional rule to allow mercenary or what's not.

I believe PEQ has optional SQL that enables the Mercenary Merchants in PoK (at least). If someone doesn't want to use mercs, they just don't run that SQL. I know it changes the NPC names, but I am not certain if it changes their class to be Merc Merchant class or not. If it does change the class, then it should be fairly simple for servers to decide to use mercs or not by enabling the merchants or not. For anyone using Live collects (such as the ones Robregen has done), people would manually have to change all other zones with merc merchants like Crescent Reach or other newbie zones that might have them.

A rule would probably be fine, but I think the simplest rule would be to just have it disable the merchants. If it doesn't send class 71, then they can't get the mercenaries. We could probably add a rule to the fill spawn struct function to change class 71 to class 1 or something instead if mercs are disabled.

And yeah, from what I have read, confidence only effects how many NPCs they can have on their hate list before they start fleeing. There were some interesting posts on ZAMs about people finding ways around having their mercs flee when multiples were attacking. It probably wouldn't be too hard to copy that mechanic based on the info provided, but to me that sounds like implementing an exploit from Live just to try to copy it exactly.

I agree with Secrets that Live probably uses min/max for Mercs as well as stats instead of equiping armor. There is really no need to have them equip actual items unless they were going to allow those items to be changed out by players. Otherwise, it is just a waste of DB space for them and more DB hits than would be required without them.

I know there was a time when anytime you saw an NPC with a weapon, they actually had that weapon in their inventory. I am not sure exactly when that changed, but I am positive they don't do that all of the time anymore. I know at least by TBS they had started just sending weapon models with wearchange packets for NPCs that didn't actually wield the weapon they showed. I know this because I remember seeing an NPC in Stonehive with a weapon that wasn't on its corpse after I killed it (and wasn't something that is included with that NPC model). They probably changed that to be more flexible and maybe to mess with ShowEQ users as well, since I know people used to look for NPCs with weapons equipped so they knew which ones to go after.

BTW, awesome work so far, Secrets! Hopefully we will be ready to merge with the trunk soon.


All times are GMT -4. The time now is 11:47 AM.

Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.