diff --git a/changelog.txt b/changelog.txt index c37ee7211..34682c709 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- + +== 04/04/2013== +demonstar55: Implemented Salvage AA +required SQL: 2013_04_08_Salvage.sql +script: generate_salvage.py - will generate the entries for some exceptions for salvage returns. + == 04/04/2013 == demonstar55: Implemented SE_ForageAdditionalItems as a bonus required SQL: 2013_04_04_NaturesBounty.sql diff --git a/utils/defaults/eqemu_config.xml b/utils/defaults/eqemu_config.xml index 7b05c04ce..7357cdb60 100644 --- a/utils/defaults/eqemu_config.xml +++ b/utils/defaults/eqemu_config.xml @@ -1,4 +1,4 @@ - + setme diff --git a/utils/defaults/eqemu_config.xml.full b/utils/defaults/eqemu_config.xml.full index 74065a510..859dafa33 100644 --- a/utils/defaults/eqemu_config.xml.full +++ b/utils/defaults/eqemu_config.xml.full @@ -1,4 +1,4 @@ - + setme diff --git a/utils/scripts/generate_salvage.py b/utils/scripts/generate_salvage.py new file mode 100644 index 000000000..40ed7821d --- /dev/null +++ b/utils/scripts/generate_salvage.py @@ -0,0 +1,84 @@ +#! /usr/bin/env python +# Requires MySQLdb (python-mysqldb) + +import MySQLdb as mdb +import xml.etree.ElementTree as ET +import sys + +def main(): + con = None + table = "tradeskill_recipe_entries" + db = "eq" + user = "eq" + password = "eq" + host = "localhost" + + try: + tree = ET.parse('eqemu_config.xml') + database = tree.getroot().find('database') + db = database.find('db').text + user = database.find('username').text + password = database.find('password').text + host = database.find('host').text + + except: + print("Trying with defaults") + print("Do you have a valid XML?") + + try: + con = mdb.connect(host, user, password, db) + + cur = con.cursor() + cur.execute("SELECT MAX(id) FROM `tradeskill_recipe") + data = cur.fetchone() + highest = data[0] + for recipe_id in range(1, highest+1): + genflag = False + complist = [] + cur.execute("SELECT item_id,componentcount FROM " + table + " WHERE componentcount>0 AND recipe_id=" + str(recipe_id)) + rows = cur.fetchall() + for row in rows: + complist.append(row) + + faillist = [] + cur.execute("SELECT item_id,failcount FROM " + table + " WHERE failcount>0 AND recipe_id=" + str(recipe_id)) + rows = cur.fetchall() + for row in rows: + faillist.append(row) + + # Remove any items that are returned on a failure + for item in faillist: + if item in complist: + genflag = True + complist.remove(item) + + # Remove some items that don't make sense + for item in faillist: + if item[0] == 10062: + for item2 in complist: + if item2[0] == 93510: + genflag = True + complist.remove(item2) + if item[0] == 93618: + for item2 in complist: + if item2[0] in [93508, 93509]: + genflag = True + complist.remove(item2) + + + if genflag: + for item in complist: + cur.execute("INSERT INTO `" + table + "` (`recipe_id`, `item_id`, `componentcount`, `salvagecount`) VALUES ('" + str(recipe_id) + "', '" + str(item[0]) + "', '0', '" + str(item[1]) + "');\n") + + except mdb.Error, e: + print("Error %d: %s", e.args[0],e.args[1]) + sys.exit(1) + + finally: + if con: + con.close() + + return 0 + +if __name__ == '__main__': + main() diff --git a/utils/sql/git/required/2013_04_08_Salvage.sql b/utils/sql/git/required/2013_04_08_Salvage.sql new file mode 100644 index 000000000..a98aad2f3 --- /dev/null +++ b/utils/sql/git/required/2013_04_08_Salvage.sql @@ -0,0 +1,11 @@ +-- Add row to tre +ALTER TABLE `tradeskill_recipe_entries` ADD `salvagecount` tinyint(2) DEFAULT '0' NOT NULL AFTER `componentcount`; + +-- Fix level req on Salvage +UPDATE `altadv_vars` SET `level_inc` = '5' WHERE `skill_id` = '997'; + +-- Set aa_effects for Salvage +INSERT INTO `aa_effects` (`id`, `aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('2374', '997', '1', '313', '5', '0'); +INSERT INTO `aa_effects` (`id`, `aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('2375', '998', '1', '313', '15', '0'); +INSERT INTO `aa_effects` (`id`, `aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('2376', '999', '1', '313', '25', '0'); + diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index d0c716cb0..cb2502c35 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -837,6 +837,9 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) break; case SE_ForageAdditionalItems: newbon->ForageAdditionalItems += base1; + break; + case SE_Salvage: + newbon->SalvageChance += base1; break; case SE_ArcheryDamageModifier: newbon->ArcheryDamageModifier += base1; @@ -2197,6 +2200,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_ForageAdditionalItems: newbon->ForageAdditionalItems += effect_value; + break; + + case SE_Salvage: + newbon->SalvageChance += effect_value; break; case SE_ArcheryDamageModifier: @@ -3342,6 +3349,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) spellbonuses.ForageAdditionalItems = effect_value; aabonuses.ForageAdditionalItems = effect_value; itembonuses.ForageAdditionalItems = effect_value; + break; + + case SE_Salvage: + spellbonuses.SalvageChance = effect_value; + aabonuses.SalvageChance = effect_value; + itembonuses.SalvageChance = effect_value; break; case SE_ArcheryDamageModifier: diff --git a/zone/common.h b/zone/common.h index 3a0171f8d..26b73c258 100644 --- a/zone/common.h +++ b/zone/common.h @@ -347,6 +347,7 @@ struct StatBonuses { uint8 FrontalBackstabChance; // Chance to backstab from the front for full damage uint8 ConsumeProjectile; // Chance to not consume arrow. uint8 ForageAdditionalItems; // Chance to forage another item. + uint8 SalvageChance; // Chance to salvage a tradeskill components on fail. uint16 ArcheryDamageModifier; // Increase Archery Damage by percent bool SecondaryDmgInc; // Allow off hand weapon to recieve damage bonus. uint16 GiveDoubleAttack; // Allow classes to double attack with a specified chance. diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index fa64de858..9b1973438 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2716,6 +2716,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_ArcheryDamageModifier: case SE_ConsumeProjectile: case SE_ForageAdditionalItems: + case SE_Salvage: case SE_FrontalBackstabChance: case SE_FrontalBackstabMinDmg: case SE_TripleBackstab: diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 0f050368d..6c92fb158 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -1060,6 +1060,21 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { SummonItem(itr->first, itr->second); itr++; } + + // Rolls on each item, is possible to return everything + int SalvageChance = aabonuses.SalvageChance + itembonuses.SalvageChance + spellbonuses.SalvageChance; + // Skip check if not a normal TS or if a quest recipe these should be nofail, but check amyways + if(SalvageChance && spec->tradeskill != 75 && !spec->quest) { + itr = spec->salvage.begin(); + uint8 sc = 0; + while(itr != spec->salvage.end()) { + for(sc = 0; sc < itr->second; sc++) + if(MakeRandomInt(0,99) < SalvageChance) + SummonItem(itr->first, 1); + itr++; + } + } + } return(false); } @@ -1404,8 +1419,45 @@ bool ZoneDatabase::GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id } mysql_free_result(result); } - safe_delete_array(query); - + + // Pull the salvage list + qlen = MakeAnyLenString(&query, "SELECT item_id,salvagecount FROM tradeskill_recipe_entries" + " WHERE salvagecount>0 AND recipe_id=%u", recipe_id); + + spec->salvage.clear(); + // Don't bother with the query if TS is nofail + if (!spec->nofail) { + if (RunQuery(query, qlen, errbuf, &result)) { + qcount = mysql_num_rows(result); + uint8 r; + for(r = 0; r < qcount; r++) { + row = mysql_fetch_row(result); + uint32 item = (uint32)atoi(row[0]); + uint8 num = (uint8)atoi(row[1]); + spec->salvage.push_back(pair(item, num)); + } + mysql_free_result(result); + } + + // Previous query returned nothing, default to component list + if (!spec->salvage.size()) { + qlen = MakeAnyLenString(&query, "SELECT item_id,componentcount FROM tradeskill_recipe_entries" + " WHERE componentcount>0 AND recipe_id=%u", recipe_id); + if (RunQuery(query, qlen, errbuf, &result)) { + qcount = mysql_num_rows(result); + uint8 r; + for(r =0; r < qcount; r++) { + row = mysql_fetch_row(result); + uint32 item = (uint32)atoi(row[0]); + uint8 num = (uint8)atoi(row[1]); + spec->salvage.push_back(pair(item, num)); + } + mysql_free_result(result); + } + } + } + safe_delete_array(query); + return(true); } diff --git a/zone/zonedb.h b/zone/zonedb.h index 545811525..d0f5dc9be 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -46,6 +46,7 @@ struct DBTradeskillRecipe_Struct { bool replace_container; vector< pair > onsuccess; vector< pair > onfail; + vector< pair > salvage; string name; uint8 must_learn; bool has_learnt;