PDA

View Full Version : tradeskill.cpp enhancements


eq4me
09-09-2006, 12:48 PM
I am not quite done yet but the changes I implemented so far are working fine and will bring the workings of the tradeskill success rates alot closer to life.


--- zone/tradeskills.cpp-orig 2006-09-07 19:04:51.927543012 +0000
+++ zone/tradeskills.cpp 2006-09-10 00:42:31.938770546 +0000
@@ -652,6 +652,36 @@
float chance = 0;
+ float skillup_modifier;
+ sint16 thirdstat = 0;
+ sint16 stat_modifier = -15;
+ sint16 success_multiplier = 0;
+
+ // Rework based on the info on eqtraders.com
+ // http://mboards.eqtraders.com/eq/showthread.php?t=22246
+ // 09/10/2006 v0.1 (eq4me) Todo: Implementing new formula for skillup chance.
+
+ // Some tradeskills are more eqal then others. ;-)
+ if (tradeskill == (ALCHEMY || FLETCHING || JEWELRY_MAKING || POTTERY)) {
+ skillup_modifier = 4;
+ } else if (tradeskill == (BAKING || BREWING)) {
+ skillup_modifier = 3;
+ } else if (tradeskill == (RESEARCH)) {
+ skillup_modifier = 1;
+ } else
+ skillup_modifier = 2;
+
+ // Some tradeskills take the higher of one additional stat beside INT and WIS
+ // to determine the skillup rate. Additionally these tradeskills do not have an
+ // -15 modifier on their statbonus.
+ if (tradeskill == ( FLETCHING || MAKE_POISON)) {
+ thirdstat = GetDEX();
+ stat_modifier = 0;
+ } else if (tradeskill == (BLACKSMITHING)) {
+ thirdstat = GetSTR();
+ stat_modifier = 0;
+ }
+
+ sint16 higher_from_int_wis = (GetINT() > GetWIS()) ? GetINT() : GetWIS();
+ sint16 bonusstat = (higher_from_int_wis > thirdstat) ? higher_from_int_wis : thirdstat;

- // statbonus 20%/10% with 200 + 0.05% / 0.025% per point above 200
- float wisebonus = (m_pp.WIS > 200) ? 20 + ((m_pp.WIS - 200) * 0.05) : m_pp.WIS * 0.1;
- float intbonus = (m_pp.INT > 200) ? 10 + ((m_pp.INT - 200) * 0.025) : m_pp.INT * 0.05;
+ float skillupbonus = (bonusstat > 200) ? 10 + ((bonusstat - 200) * 0.025) : bonusstat * 0.05;

@@ -662,16 +692,37 @@
chance = 100; //cannot fail.
+ #ifdef TRADESKILL_SPAM
+ Message(0, "This combine cannot fail.");
+ #endif
} else if(((sint16)user_skill - (sint16)spec->skill_needed) < 0) {
- chance = 0;
- //impossible... is there a message for this???
- } else if (((sint16)user_skill - (sint16)spec->trivial) >= 0) {
- chance = 80+wisebonus-10; // 80% basechance + max 20% stats
+ // Minimum chance is always 5
+ chance = 5;
+ } else if(((sint16)user_skill - (sint16)spec->trivial) == 0) {
+ // At reaching trivial the chance goes to 95% going up an additional
+ // percent for every 40 skillpoints above the trivial.
+ // The success rate is not modified through stats.
+ // Mastery AAs are unaccounted for so far.
+ // chance_AA = chance + ((100 - chance) * mastery_modifier)
+ // But the 95% limit with an additional 1% for every 40 skill points
+ // above critical still stands.
+ // Mastery modifier is: 10%/25%/50% for rank one/two/three
+ chance = 95;
+ Message_StringID(4,TRADESKILL_TRIVIAL);
+ } else if (((sint16)user_skill - (sint16)spec->trivial) > 0) {
+ chance = (sint16)((user_skill - spec->trivial) / 40) + 95;
+ if (chance > 100) {
+ chance = 100;
+ }
Message_StringID(4,TRADESKILL_TRIVIAL);
} else {
- if ((spec->trivial - user_skill) < 20) {
- // 40 base chance success + max 40% skill + 20% max stats
- chance = 40 + wisebonus + 40 - ((spec->trivial - user_skill)*2);
+ // For trivials over 68 the chance is (skill - 0.75*trivial) +51.5
+ // For trivial up to 68 the chance is (skill - trivial) + 66
+ if (spec->trivial >= 68) {
+ chance = (user_skill - (0.75*spec->trivial)) + 51.5;
}
else {
- // 0 base chance success + max 30% skill + 10% max stats
- chance = 0 + (wisebonus/2) + 30 - (((spec->trivial - user_skill) * (spec->trivial - user_skill))*0.01875);
+ chance = (user_skill - spec->trivial) + 66;
+ }
+ //Just because I am paranoid
+ if (chance >95) {
+ chance = 95;
}
@@ -680,3 +732,3 @@
// skillincrease?
- if ((55-(user_skill*0.236))+intbonus > (float)rand()/RAND_MAX*100) {
+ if ((55-(user_skill*0.236))+skillupbonus > (float)rand()/RAND_MAX*100) {
SetSkill(tradeskill, GetRawSkill(tradeskill) + 1);
@@ -690,2 +742,7 @@

+ #ifdef TRADESKILL_SPAM
+ Message(0, "Current skill: %d , Trivial: %d , Success chance: %f percent. , skillupbonus: %f", user_skill , spec->trivial , chance , skillupbonus);
+ Message(0, "Bonusstat: %d , INT: %d , WIS: %d , DEX: %d , STR: %d", bonusstat , GetINT() , GetWIS() , GetDEX() , GetSTR());
+ #endif
+
itr = spec->onsuccess.begin();
@@ -700,2 +757,7 @@

+ #ifdef TRADESKILL_SPAM
+ Message(0, "Current skill: %d , Trivial: %d , Success chance: %f percent. , skillupbonus: %f", user_skill , spec->trivial , chance , skillupbonus);
+ Message(0, "Bonusstat: %d , INT: %d , WIS: %d , DEX: %d , STR: %d", bonusstat , GetINT() , GetWIS() , GetDEX() , GetSTR());
+ #endif

eq4me
09-10-2006, 12:46 AM
Ok, some bugs fixed and implemented the skillup formula. Unless there are bugs creeping up I consider it done for now. Maybe I will get back to it later and implement the Tradeskill AAs. Depends if this makes it into the EQEmu source. ;)

The ups
For determining skillups now the higher of INT or WIS(and in some cases STR or DEX too) will be used instead of just INT.
If you succeed on an item the chance for an skillup is higher.
You have now a good chance to succeed on an item with an trivial more than 30 above your skill.
Once an item has reached trivial the chance to succeed is 95% plus 1% per 40 skillpoints above trivial.

The downs
Chance to succeed is no longer modified by any stat. (Not really an issue since the success rates with a skill well under trivial are so much better)
Skillups might be slower on high skill levels.
Some tradeskills are harder to raise than others.

Look for my comments how to tweak the success and skillup rates to your liking.

Below is a diff to tradeskills.cpp and client.h from EQEmu Version 7.0.0-845


--- zone/tradeskills.cpp-orig 2006-09-07 19:04:51.927543012 +0000
+++ zone/tradeskills.cpp 2006-09-10 12:26:01.738867547 +0000
@@ -652,6 +652,41 @@
float chance = 0;
+ float skillup_modifier;
+ sint16 thirdstat = 0;
+ sint16 stat_modifier = 15;
+ uint16 success_modifier;
+
+ // Rework based on the info on eqtraders.com
+ // http://mboards.eqtraders.com/eq/showthread.php?t=22246
+ // 09/10/2006 v0.1 (eq4me)
+ // 09/11/2006 v0.2 (eq4me)
+ // Todo:
+ // Implementing AAs
+ // Success modifiers based on recipes
+ // Skillup modifiers based on the rarity of the ingredients
+
+ // Some tradeskills are more eqal then others. ;-)
+ // If you want to customize the stage1 success rate do it here.
+ // Remember: skillup_modifier is (float). Lower is better.
+ if (tradeskill == ALCHEMY || tradeskill == FLETCHING || tradeskill == JEWELRY_MAKING || tradeskill == POTTERY) {
+ skillup_modifier = 4;
+ } else if (tradeskill == BAKING || tradeskill == BREWING) {
+ skillup_modifier = 3;
+ } else if (tradeskill == RESEARCH) {
+ skillup_modifier = 1;
+ } else
+ skillup_modifier = 2;
+
+ // Some tradeskills take the higher of one additional stat beside INT and WIS
+ // to determine the skillup rate. Additionally these tradeskills do not have an
+ // -15 modifier on their statbonus.
+ if (tradeskill == FLETCHING || tradeskill == MAKE_POISON) {
+ thirdstat = GetDEX();
+ stat_modifier = 0;
+ } else if (tradeskill == BLACKSMITHING) {
+ thirdstat = GetSTR();
+ stat_modifier = 0;
+ }

- // statbonus 20%/10% with 200 + 0.05% / 0.025% per point above 200
- float wisebonus = (m_pp.WIS > 200) ? 20 + ((m_pp.WIS - 200) * 0.05) : m_pp.WIS * 0.1;
- float intbonus = (m_pp.INT > 200) ? 10 + ((m_pp.INT - 200) * 0.025) : m_pp.INT * 0.05;
+ sint16 higher_from_int_wis = (GetINT() > GetWIS()) ? GetINT() : GetWIS();
+ sint16 bonusstat = (higher_from_int_wis > thirdstat) ? higher_from_int_wis : thirdstat;

@@ -662,23 +697,37 @@
chance = 100; //cannot fail.
+ #ifdef TRADESKILL_SPAM
+ Message(0, "...This combine cannot fail.");
+ #endif
} else if(((sint16)user_skill - (sint16)spec->skill_needed) < 0) {
- chance = 0;
- //impossible... is there a message for this???
- } else if (((sint16)user_skill - (sint16)spec->trivial) >= 0) {
- chance = 80+wisebonus-10; // 80% basechance + max 20% stats
+ // Minimum chance is always 5
+ chance = 5;
+ } else if(((sint16)user_skill - (sint16)spec->trivial) == 0) {
+ // At reaching trivial the chance goes to 95% going up an additional
+ // percent for every 40 skillpoints above the trivial.
+ // The success rate is not modified through stats.
+ // Mastery AAs are unaccounted for so far.
+ // chance_AA = chance + ((100 - chance) * mastery_modifier)
+ // But the 95% limit with an additional 1% for every 40 skill points
+ // above critical still stands.
+ // Mastery modifier is: 10%/25%/50% for rank one/two/three
+ chance = 95;
+ Message_StringID(4,TRADESKILL_TRIVIAL);
+ } else if (((sint16)user_skill - (sint16)spec->trivial) > 0) {
+ chance = (sint16)((user_skill - spec->trivial) / 40) + 95;
+ if (chance > 100) {
+ chance = 100;
+ }
Message_StringID(4,TRADESKILL_TRIVIAL);
} else {
- if ((spec->trivial - user_skill) < 20) {
- // 40 base chance success + max 40% skill + 20% max stats
- chance = 40 + wisebonus + 40 - ((spec->trivial - user_skill)*2);
+ // For trivials over 68 the chance is (skill - 0.75*trivial) +51.5
+ // For trivial up to 68 the chance is (skill - trivial) + 66
+ if (spec->trivial >= 68) {
+ chance = (user_skill - (0.75*spec->trivial)) + 51.5;
}
else {
- // 0 base chance success + max 30% skill + 10% max stats
- chance = 0 + (wisebonus/2) + 30 - (((spec->trivial - user_skill) * (spec->trivial - user_skill))*0.01875);
+ chance = (user_skill - spec->trivial) + 66;
}
-
-//Is there a reason we dont use CheckIncreaseSkill()?
- // skillincrease?
- if ((55-(user_skill*0.236))+intbonus > (float)rand()/RAND_MAX*100) {
- SetSkill(tradeskill, GetRawSkill(tradeskill) + 1);
- //Message(4, "You have become better at (skillid=%i)", tradeskill);
+ //Just because I am paranoid
+ if (chance >95) {
+ chance = 95;
}
@@ -688,4 +738,11 @@
if ((tradeskill==75) || GetGM() || (chance > res)){
+ success_modifier = 1;
+ CheckIncreaseTradeskill(bonusstat, stat_modifier, skillup_modifier, success_modifier, tradeskill);
Message_StringID(4,TRADESKILL_SUCCEED);

+ #ifdef TRADESKILL_SPAM
+ Message(0, "...Current skill: %d , Trivial: %d , Success chance: %f percent", user_skill , spec->trivial , chance);
+ Message(0, "...Bonusstat: %d , INT: %d , WIS: %d , DEX: %d , STR: %d", bonusstat , GetINT() , GetWIS() , GetDEX() , GetSTR());
+ #endif
+
itr = spec->onsuccess.begin();
@@ -698,4 +755,11 @@
} else {
+ success_modifier = 2; // Halves the chance
+ CheckIncreaseTradeskill(bonusstat, stat_modifier, skillup_modifier, success_modifier, tradeskill);
Message_StringID(4,TRADESKILL_FAILED);

+ #ifdef TRADESKILL_SPAM
+ Message(0, "...Current skill: %d , Trivial: %d , Success chance: %f percent", user_skill , spec->trivial , chance);
+ Message(0, "...Bonusstat: %d , INT: %d , WIS: %d , DEX: %d , STR: %d", bonusstat , GetINT() , GetWIS() , GetDEX() , GetSTR());
+ #endif
+
itr = spec->onfail.begin();
@@ -711,2 +776,40 @@

+void Client::CheckIncreaseTradeskill(sint16 bonusstat, sint16 stat_modifier, float skillup_modifier, uint16 success_modifier, uint16 tradeskill)
+{
+ uint16 current_raw_skill = GetRawSkill(tradeskill);
+ float chance_stage2 = 0;
+
+ //A successfull combine doubles the stage1 chance for an skillup
+ //Some tradeskill are harder than others. See above for more.
+ float chance_stage1 = (bonusstat - stat_modifier) / (skillup_modifier * success_modifier);
+
+ //In stage2 the only thing that matters is your current unmodified skill.
+ //If you want to customize here you probbably need to implement your own
+ //formula instead of tweaking the below one.
+ if (chance_stage1 > (float)rand()/RAND_MAX*100) {
+ if (current_raw_skill < 15) {
+ // Allways succeed
+ chance_stage2 = 100;
+ } else if (current_raw_skill < 175) {
+ //From skill 16 to 174 your chance of success falls linearly from 92% to 13%.
+ chance_stage2 = (200 - current_raw_skill) / 2;
+ } else {
+ //At skill 175, your chance of success falls linearly from 12.5% to 2.5% at skill 300.
+ chance_stage2 = 12.5 - (.08 * (current_raw_skill - 175));
+ }
+ }
+
+ if (chance_stage2 > (float)rand()/RAND_MAX*100) {
+ //Only if stage1 and stage2 succeeded you get a skillup.
+ SetSkill(tradeskill, current_raw_skill + 1);
+ }
+
+ #ifdef TRADESKILL_SPAM
+ Message(0, "...skillup_modifier: %f , success_modifier: %d , stat modifier: %d", skillup_modifier , success_modifier , stat_modifier);
+ Message(0, "...Stage1 chance was: %f percent", chance_stage1);
+ Message(0, "...Stage2 chance was: %f percent. 0 percent means stage1 failed", chance_stage2);
+ #endif
+ return;
+}
+

--- zone/client.h-orig 2006-09-10 12:39:04.311101098 +0000
+++ zone/client.h 2006-09-10 10:48:51.852853481 +0000
@@ -491,2 +491,4 @@
bool TradeskillExecute(DBTradeskillRecipe_Struct *spec, uint16 tradeskill);
+ //eq4me additions
+ void CheckIncreaseTradeskill(sint16, sint16, float, uint16, uint16);

InsaneWallaby
09-10-2006, 06:10 AM
I don't need to look at the code to know that your changes will make you good peoples. The tradeskilling right now is ridiculous--whoever heard of failing 30-50% of your metal bits with a 144 smithing skill? Also, good with the tradeskilling difficulty being changed according to skill. Brewing, for instance, was always much harder to put up than something like jewelcraft, if I remember from my five years ago properly. I remember, at most, about 10% of failures on supertrivial items, and also remember being able to make things like a grandmaster smithy hammer with 1/3 success rate at 250 skill, while EQTraders rates it at a trivial of over 300. Thanks!

eq4me
09-10-2006, 06:52 AM
The tradeskilling right now is ridiculous--whoever heard of failing 30-50% of your metal bits with a 144 smithing skill?
Yea, that got me started in the first place.

Also, good with the tradeskilling difficulty being changed according to skill. Brewing, for instance, was always much harder to put up than something like jewelcraft, if I remember from my five years ago properly.
There was an tradeskill revamp in 2005. See http://mboards.eqtraders.com/eq/showthread.php?t=22246
Brewing is a bit easier than Jewelcraft, but not as easy as Smithing.

@fathernitwit: How about raising the r_value for tradeskills in zone/maxskill.h to 300?

Right now I am thinking about some scripts to grab and import all known recipes from eqtraders.com.

eq4me
09-11-2006, 10:15 AM
@fathernitwit: How about raising the r_value for tradeskills in zone/maxskill.h to 300?


To answer my own question:

Probably not without some changes to part of the code or even the database, if its an int8 value too.

Eg. zone/client.cpp

void Client::SetSkill(int skillid, int8 value) {
if (skillid > HIGHEST_SKILL)
return;
m_pp.skills[skillid] = value; // We need to be able to #setskill 254 and 255 to reset skills

if(value <= 252) {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct));
SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer;
skill->skillId=skillid;
skill->value=value;
QueuePacket(outapp);
safe_delete(outapp);
}

fathernitwit
09-11-2006, 12:56 PM
I will look over this and try to get it in some time soon.

Its not likely to be a small amount of work to support skills over 252, since so much of the code and DB treat 253-255 as special values.. but your welcome to try.

Right now I am thinking about some scripts to grab and import all known recipes from eqtraders.com.

Where do you think all the recipes we have came from? I havent run it in several months, but most new recipes dont really apply anyhow.

fathernitwit
09-11-2006, 02:38 PM
Have a look over what I checked in. I rewrote some of it (success min/max) since it still didnt look right. Let me know how it works out, I havent tested it.

A couple comments:
- use the log system to do conditional logging, not ifdef'd messages
- never cast unless you have very good reason to do so, it all too often masks or creates bugs.

eq4me
09-11-2006, 07:53 PM
Yea, that looks better than my attempt.

Btw. The "Checking Out A Branch From CVS On UNIX" in the Wiki might not be quite right.
At least I get an "connect to cvs.sourceforge.net(66.35.250.207):2401 failed: No route to host" right now


cvs -d:pserver:anonymous@eqemulator.cvs.sourceforge.net :/cvsroot/eqemulator login
cvs -z3 -d:pserver:anonymous@eqemulator.cvs.sourceforge.net :/cvsroot/eqemulator co -r Development -P EQEmuCVS

works.

Where do you think all the recipes we have came from? I havent run it in several months, but most new recipes dont really apply anyhow.
I dont have time to check this right now but I was under the impression that there are quite some working recipes missing that where available in cavedudes database. I have a look when I get home from work.

fathernitwit
09-12-2006, 01:41 PM
Btw. The "Checking Out A Branch From CVS On UNIX" in the Wiki might not be quite right.
its a wiki, just fix it.