Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Bug Reports

Development::Bug Reports Post detailed bug reports and what you would like to see next in the emu here.

Reply
 
Thread Tools Display Modes
  #1  
Old 12-01-2008, 12:34 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default GM Skill Training has no Cost

Currently, when someone trains a skill at their class GM, it shows on the client that it is subtracting the amount of coin that it is supposed to, but when you zone, the coin reappears in your inventory. It looks like the problem is that we don't do any coin removal in the code for GM training here:

client_process.cpp
Code:
void Client::OPGMTrainSkill(const EQApplicationPacket *app)
{
	if(!m_pp.points)
		return;

	GMSkillChange_Struct* gmskill = (GMSkillChange_Struct*) app->pBuffer;
	
	Mob* pTrainer = entity_list.GetMob(gmskill->npcid);
	if(!pTrainer || !pTrainer->IsNPC() || pTrainer->GetClass() < WARRIORGM || pTrainer->GetClass() > BERSERKERGM)
		return;
	
	//you can only use your own trainer, client enforces this, but why trust it
	int trains_class = pTrainer->GetClass() - (WARRIORGM - WARRIOR);
	if(GetClass() != trains_class)
		return;
	
	//you have to be somewhat close to a trainer to be properly using them
	if(DistNoRoot(*pTrainer) > USE_NPC_RANGE2)
		return;
	
	if (gmskill->skillbank == 0x01)
	{
		// languages go here
		if (gmskill->skill_id > 25)
		{
			cout << "Wrong Training Skill (languages)" << endl;
			DumpPacket(app);
			return;
		}
		cout << "Training language: " << gmskill->skill_id << endl;
		IncreaseLanguageSkill(gmskill->skill_id);
	}
	else if (gmskill->skillbank == 0x00)
	{
		// normal skills go here
		if (gmskill->skill_id > HIGHEST_SKILL)
		{
			cout << "Wrong Training Skill (abilities)" << endl;
			DumpPacket(app);
			return;
		}

		SkillType skill = (SkillType) gmskill->skill_id;

		if(!CanHaveSkill(skill)) {
			mlog(CLIENT__ERROR, "Tried to train skill %d, which is not allowed.", skill);
			return;
		}
		
		int16 skilllevel = GetRawSkill(skill);
		if(skilllevel == 0) {
			//this is a new skill..
			int16 t_level = SkillTrainLevel(skill, GetClass());
			if (t_level == 0)
			{
				return;
			}
			SetSkill(skill, t_level);
		} else {
			switch(skill) {
			case BREWING:
			case MAKE_POISON:
			case TINKERING:
			case RESEARCH:
			case ALCHEMY:
			case BAKING:
			case TAILORING:
			case BLACKSMITHING:
			case FLETCHING:
			case JEWELRY_MAKING:
			case POTTERY:
				if(skilllevel >= RuleI(Skills, MaxTrainTradeskills)) {
					Message_StringID(13, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
					return;
				}
			default:
				break;
			}
            // Client train a valid skill
			SetSkill(skill, skilllevel + 1);
		}
	}
	m_pp.points--;
}
I will try to figure out the formula for skill prices and if I can, I will try to use the same code that is used when purchasing items from merchants to allow GM Training to actually have a cost.

If anyone has suggestions or other info on this, feel free to post it
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

Last edited by trevius; 12-01-2008 at 09:01 AM..
Reply With Quote
  #2  
Old 12-01-2008, 01:01 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Looks like this is where merchants take money for buying items, so some of the code should be usable for GM Trainers once the formula for prices on skills is figured out.

client_packet.cpp
Code:
void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app)
{
	RDTSC_Timer t1;
	t1.start();
	Merchant_Sell_Struct* mp=(Merchant_Sell_Struct*)app->pBuffer;
#if EQDEBUG >= 5
		LogFile->write(EQEMuLog::Debug, "%s, purchase item..", GetName());
		DumpPacket(app);
#endif

	int merchantid;
	bool tmpmer_used = false;
	Mob* tmp = entity_list.GetMob(mp->npcid);
	
	if (tmp == 0 || !tmp->IsNPC() || tmp->GetClass() != MERCHANT)
		return;

	if (mp->quantity < 1) return;
	
	//you have to be somewhat close to them to be properly using them
	if(DistNoRoot(*tmp) > USE_NPC_RANGE2)
		return;
	
	merchantid=tmp->CastToNPC()->MerchantType;
	
	uint32 item_id = 0;
	std::list<MerchantList> merlist = zone->merchanttable[merchantid];
	std::list<MerchantList>::const_iterator itr;
	for(itr = merlist.begin();itr != merlist.end();itr++){
		MerchantList ml = *itr;
		if(mp->itemslot == ml.slot){
			item_id = ml.item;
			break;
		}
	}
	const Item_Struct* item = NULL;
	int32 prevcharges = 0;
	if (item_id == 0) { //check to see if its on the temporary table
		std::list<TempMerchantList> tmp_merlist = zone->tmpmerchanttable[tmp->GetNPCTypeID()];
		std::list<TempMerchantList>::const_iterator tmp_itr;
		TempMerchantList ml;
		for(tmp_itr = tmp_merlist.begin();tmp_itr != tmp_merlist.end();tmp_itr++){
			ml = *tmp_itr;
			if(mp->itemslot == ml.slot){
				item_id = ml.item;
				tmpmer_used = true;
				prevcharges = ml.charges;
				break;
			}
		}
	} 
	item = database.GetItem(item_id);
	if (!item){
		//error finding item, client didnt get the update packet for whatever reason, roleplay a tad
		Message(15,"%s tells you 'Sorry, that item is for display purposes only.' as they take the item off the shelf.",tmp->GetCleanName());						
		EQApplicationPacket* delitempacket = new EQApplicationPacket(OP_ShopDelItem, sizeof(Merchant_DelItem_Struct));
		Merchant_DelItem_Struct* delitem = (Merchant_DelItem_Struct*)delitempacket->pBuffer;
		delitem->itemslot = mp->itemslot;
		delitem->npcid = mp->npcid;
		delitem->playerid = mp->playerid;
		delitempacket->priority = 6;
		entity_list.QueueCloseClients(tmp,delitempacket); //que for anyone that could be using the merchant so they see the update
		safe_delete(delitempacket);
		return;
	}
	if (CheckLoreConflict(item))
	{
		Message(15,"You can only have one of a lore item.");
		return;
	}
	if(tmpmer_used && (mp->quantity > prevcharges))
		mp->quantity = prevcharges;
	
	EQApplicationPacket* outapp = new EQApplicationPacket(OP_ShopPlayerBuy, sizeof(Merchant_Sell_Struct));
	Merchant_Sell_Struct* mpo=(Merchant_Sell_Struct*)outapp->pBuffer;
	mpo->quantity = mp->quantity;
	mpo->playerid = mp->playerid;
	mpo->npcid = mp->npcid;
	mpo->itemslot=mp->itemslot;
	
	sint16 freeslotid=0;
	ItemInst* inst = database.CreateItem(item, mp->quantity);

	bool stacked = TryStacking(inst);
	if(!stacked)
		freeslotid = m_inv.FindFreeSlot(false, true, item->Size);
	
	//make sure we are not completely full...
	if(freeslotid == SLOT_CURSOR) {
		if(m_inv.GetItem(SLOT_CURSOR) != NULL) {
			Message(13, "You do not have room for any more items.");
			safe_delete(outapp);
			safe_delete(inst);
			return;
		}
	}
	
	mpo->price = (item->Price*(1/.884)*Client::CalcPriceMod(tmp,false))*mp->quantity;
	if(freeslotid == SLOT_INVALID || !TakeMoneyFromPP(mpo->price))
	{
		safe_delete(outapp);
		safe_delete(inst);
		return;
	}

	string packet;
	if(mp->quantity==1 && item->MaxCharges>0 && item->MaxCharges<255)
		mp->quantity=item->MaxCharges;
	
	if (!stacked && inst) {
		PutItemInInventory(freeslotid, *inst);
		SendItemPacket(freeslotid, inst, ItemPacketTrade);
	}
	else if(!stacked){
		LogFile->write(EQEMuLog::Error, "OP_ShopPlayerBuy: item->ItemClass Unknown! Type: %i", item->ItemClass);
	}

	QueuePacket(outapp);
	if(inst && tmpmer_used){
		sint32 new_charges = prevcharges - mp->quantity;
		zone->SaveTempItem(merchantid, tmp->GetNPCTypeID(),item_id,new_charges);
		if(new_charges<=0){
			EQApplicationPacket* delitempacket = new EQApplicationPacket(OP_ShopDelItem, sizeof(Merchant_DelItem_Struct));
			Merchant_DelItem_Struct* delitem = (Merchant_DelItem_Struct*)delitempacket->pBuffer;
			delitem->itemslot = mp->itemslot;
			delitem->npcid = mp->npcid;
			delitem->playerid = mp->playerid;
			delitempacket->priority = 6;
			entity_list.QueueClients(tmp,delitempacket); //que for anyone that could be using the merchant so they see the update
			safe_delete(delitempacket);
		}
	}
	safe_delete(inst);
	safe_delete(outapp);
	
	if (zone->merchantvar!=0){
		if (zone->merchantvar==7){
				LogMerchant(this,tmp,mpo,item,true);
		}
		else if ((admin>=10) && (admin<20)){
			if ((zone->merchantvar<8) && (zone->merchantvar>5))
				LogMerchant(this,tmp,mpo,item,true);
		}
		else if (admin<=20){
			if ((zone->merchantvar<8) && (zone->merchantvar>4))
				LogMerchant(this,tmp,mpo,item,true);
		}
		else if (admin<=80){
			if ((zone->merchantvar<8) && (zone->merchantvar>3))
				LogMerchant(this,tmp,mpo,item,true);
		}
		else if (admin<=100){
			if ((zone->merchantvar<9) && (zone->merchantvar>2))
				LogMerchant(this,tmp,mpo,item,true);
		}
		else if (admin<=150){
			if (((zone->merchantvar<8) && (zone->merchantvar>1)) || (zone->merchantvar==9))
				LogMerchant(this,tmp,mpo,item,true);
		}
		else if (admin<=255){
			if ((zone->merchantvar<8) && (zone->merchantvar>0))
				LogMerchant(this,tmp,mpo,item,true);	
		}
	}
	t1.stop();
	cout << "At 1: " << t1.getDuration() << endl;
	return;
}
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #3  
Old 12-01-2008, 06:53 AM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Well, unfortunately, it looks like they don't set skill costs with any type of formula as far as I can tell. So, I think we have to just get each one manually. I started a list and have the first 100 done. Only 300 more to go lol :P
Code:
Skill - Cost in Copper Pieces
1 - 0
2 - 0
3 - 0
4 - 0
5 - 0
6 - 0
7 - 0
8 - 0
9 - 0
10 - 0
11 - 0
12 - 0
13 - 0
14 - 0
15 - 1
16 - 2
17 - 3
18 - 5
19 - 7
20 - 10
21 - 13
22 - 17
23 - 21
24 - 27
25 - 33
26 - 40
27 - 49
28 - 58
29 - 68
30 - 80
31 - 92
32 - 106
33 - 121
34 - 138
35 - 156
36 - 175
37 - 196
38 - 219
39 - 243
40 - 270
41 - 297
42 - 327
43 - 359
44 - 393
45 - 428
46 - 468
47 - 506
48 - 548
49 - 593
50 - 640
51 - 689
52 - 740
53 - 795
54 - 851
55 - 911
56 - 973
57 - 1038
58 - 1105
59 - 1176
60 - 1250
61 - 1326
62 - 1406
63 - 1488
64 - 1574
65 - 1663
66 - 1756
67 - 1851
68 - 1951
69 - 2053
70 - 2160
71 - 2269
72 - 2383
73 - 2500
74 - 2621
75 - 2746
76 - 2874
77 - 3007
78 - 3144
79 - 3285
80 - 3430
81 - 3579
82 - 3732
83 - 3890
84 - 4052
85 - 4218
86 - 4389
87 - 4565
88 - 4745
89 - 4930
90 - 5120
91 - 5314
92 - 5513
93 - 5717
94 - 5927
95 - 6141
96 - 6360
97 - 6585
98 - 6814
99 - 7049
100 - 7290
101 - 
102 - 
103 - 
104 - 
105 - 
106 - 
107 - 
108 - 
109 - 
110 - 
111 - 
112 - 
113 - 
114 - 
115 - 
116 - 
117 - 
118 - 
119 - 
120 - 
121 - 
122 - 
123 - 
124 - 
125 - 
126 - 
127 - 
128 - 
129 - 
130 - 
131 - 
132 - 
133 - 
134 - 
135 - 
136 - 
137 - 
138 - 
139 - 
140 - 
141 - 
142 - 
143 - 
144 - 
145 - 
146 - 
147 - 
148 - 
149 - 
150 - 
151 - 
152 - 
153 - 
154 - 
155 - 
156 - 
157 - 
158 - 
159 - 
160 - 
161 - 
162 - 
163 - 
164 - 
165 - 
166 - 
167 - 
168 - 
169 - 
170 - 
171 - 
172 - 
173 - 
174 - 
175 - 
176 - 
177 - 
178 - 
179 - 
180 - 
181 - 
182 - 
183 - 
184 - 
185 - 
186 - 
187 - 
188 - 
189 - 
190 - 
191 - 
192 - 
193 - 
194 - 
195 - 
196 - 
197 - 
198 - 
199 - 
200 - 
201 - 
202 - 
203 - 
204 - 
205 - 
206 - 
207 - 
208 - 
209 - 
210 - 
211 - 
212 - 
213 - 
214 - 
215 - 
216 - 
217 - 
218 - 
219 - 
220 - 
221 - 
222 - 
223 - 
224 - 
225 - 
226 - 
227 - 
228 - 
229 - 
230 - 
231 - 
232 - 
233 - 
234 - 
235 - 
236 - 
237 - 
238 - 
239 - 
240 - 
241 - 
242 - 
243 - 
244 - 
245 - 
246 - 
247 - 
248 - 
249 - 
250 - 
251 - 
252 - 
253 - 
254 - 
255 - 
256 - 
257 - 
258 - 
259 - 
260 - 
261 - 
262 - 
263 - 
264 - 
265 - 
266 - 
267 - 
268 - 
269 - 
270 - 
271 - 
272 - 
273 - 
274 - 
275 - 
276 - 
277 - 
278 - 
279 - 
280 - 
281 - 
282 - 
283 - 
284 - 
285 - 
286 - 
287 - 
288 - 
289 - 
290 - 
291 - 
292 - 
293 - 
294 - 
295 - 
296 - 
297 - 
298 - 
299 - 
300 - 
301 - 
302 - 
303 - 
304 - 
305 - 
306 - 
307 - 
308 - 
309 - 
310 - 
311 - 
312 - 
313 - 
314 - 
315 - 
316 - 
317 - 
318 - 
319 - 
320 - 
321 - 
322 - 
323 - 
324 - 
325 - 
326 - 
327 - 
328 - 
329 - 
330 - 
331 - 
332 - 
333 - 
334 - 
335 - 
336 - 
337 - 
338 - 
339 - 
340 - 
341 - 
342 - 
343 - 
344 - 
345 - 
346 - 
347 - 
348 - 
349 - 
350 - 
351 - 
352 - 
353 - 
354 - 
355 - 
356 - 
357 - 
358 - 
359 - 
360 - 
361 - 
362 - 
363 - 
364 - 
365 - 
366 - 
367 - 
368 - 
369 - 
370 - 
371 - 
372 - 
373 - 
374 - 
375 - 
376 - 
377 - 
378 - 
379 - 
380 - 
381 - 
382 - 
383 - 
384 - 
385 - 
386 - 
387 - 
388 - 
389 - 
390 - 
391 - 
392 - 
393 - 
394 - 
395 - 
396 - 
397 - 
398 - 
399 - 
400 -
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!
Reply With Quote
  #4  
Old 12-01-2008, 05:56 PM
Kobaz
Hill Giant
 
Join Date: Nov 2008
Location: Gold Coast, Oz
Posts: 119
Default

With the numbers you've posted,

price = 0.001169 (level ^ 3.4) - 44.17

is very close for level >= 10, error at level 100 is 0.57%, which is 42 coppers.

Give me the other values and I'll give you a better formula.

The above formula may not work for higher levels, but it's almost certainly a polynomial curve.
Reply With Quote
  #5  
Old 12-01-2008, 06:12 PM
Kobaz
Hill Giant
 
Join Date: Nov 2008
Location: Gold Coast, Oz
Posts: 119
Default

Typo:

The formula I posted is good for level >= 31.

I would think that by PC level 5 the chances are that the char would have at least 2pp, so the insignigicant error for higher levels wouldn't matter. Use a lookup tables for the lower levels (where my formula fails spectacularly).

I'll put more than 5 minutes into it later today.
Reply With Quote
  #6  
Old 12-01-2008, 06:13 PM
trevius's Avatar
trevius
Developer
 
Join Date: Aug 2006
Location: USA
Posts: 5,946
Default

Whatever the formula is (if there is one), it starts at 15, so you would probably do (skill level - 14) before doing any other math to it.

I think a close formula would be good enough as long as it doesn't ever exceed the actual cost that the client sees. If it ever costs more than what the client sees, it could potentially cause issues. At the very least, people might not understand why they are unable to buy a skill that they believe they have enough to pay for. I will edit in the rest of the number up to 400 when I get time. It is boring work, but shouldn't take more than an hour or 2 I think. Though, once I have all of the numbers, we could probably just use them so that they are 100% accurate instead of a formula that is close to accurate.
__________________
Trevazar/Trevius Owner of: Storm Haven
Everquest Emulator FAQ (Frequently Asked Questions) - Read It!

Last edited by trevius; 12-02-2008 at 02:16 AM..
Reply With Quote
  #7  
Old 01-02-2009, 07:59 PM
cybernine186
Sarnak
 
Join Date: Feb 2008
Posts: 87
Default

bump bump.....

Whats the word?
Reply With Quote
  #8  
Old 01-04-2009, 12:28 AM
ChaosSlayer
Demi-God
 
Join Date: May 2007
Posts: 1,032
Default

umm i was prety sure you CANNOT train anything past 100
at least that what GM would normaly tell you - your skill is allreday at master
this is how i remeber it from LIVE and logicly this is how it should be
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:25 AM.


 

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 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3