9
3

GroundSpawn.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. /*
  2. EQ2Emulator: Everquest II Server Emulator
  3. Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
  4. This file is part of EQ2Emulator.
  5. EQ2Emulator is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. EQ2Emulator is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "GroundSpawn.h"
  17. #include "World.h"
  18. #include "Spells.h"
  19. #include "Rules/Rules.h"
  20. #include "../common/MiscFunctions.h"
  21. #include "../common/Log.h"
  22. extern ConfigReader configReader;
  23. extern MasterSpellList master_spell_list;
  24. extern World world;
  25. extern RuleManager rule_manager;
  26. GroundSpawn::GroundSpawn(){
  27. packet_num = 0;
  28. appearance.difficulty = 0;
  29. spawn_type = 2;
  30. appearance.pos.state = 129;
  31. number_harvests = 0;
  32. num_attempts_per_harvest = 0;
  33. groundspawn_id = 0;
  34. MHarvest.SetName("GroundSpawn::MHarvest");
  35. MHarvestUse.SetName("GroundSpawn::MHarvestUse");
  36. randomize_heading = true; // we by default randomize heading of groundspawns DB overrides
  37. }
  38. GroundSpawn::~GroundSpawn(){
  39. }
  40. EQ2Packet* GroundSpawn::serialize(Player* player, int16 version){
  41. return spawn_serialize(player, version);
  42. }
  43. int8 GroundSpawn::GetNumberHarvests(){
  44. return number_harvests;
  45. }
  46. void GroundSpawn::SetNumberHarvests(int8 val){
  47. number_harvests = val;
  48. }
  49. int8 GroundSpawn::GetAttemptsPerHarvest(){
  50. return num_attempts_per_harvest;
  51. }
  52. void GroundSpawn::SetAttemptsPerHarvest(int8 val){
  53. num_attempts_per_harvest = val;
  54. }
  55. int32 GroundSpawn::GetGroundSpawnEntryID(){
  56. return groundspawn_id;
  57. }
  58. void GroundSpawn::SetGroundSpawnEntryID(int32 val){
  59. groundspawn_id = val;
  60. }
  61. void GroundSpawn::SetCollectionSkill(const char* val){
  62. if(val)
  63. collection_skill = string(val);
  64. }
  65. const char* GroundSpawn::GetCollectionSkill(){
  66. return collection_skill.c_str();
  67. }
  68. void GroundSpawn::ProcessHarvest(Client* client) {
  69. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Process harvesting for player '%s' (%u)", client->GetPlayer()->GetName(), client->GetPlayer()->GetID());
  70. MHarvest.lock();
  71. vector<GroundSpawnEntry*>* groundspawn_entries = GetZone()->GetGroundSpawnEntries(groundspawn_id);
  72. vector<GroundSpawnEntryItem*>* groundspawn_items = GetZone()->GetGroundSpawnEntryItems(groundspawn_id);
  73. Item* master_item = 0;
  74. Item* master_rare = 0;
  75. Item* item = 0;
  76. Item* item_rare = 0;
  77. int16 lowest_skill_level = 0;
  78. int16 table_choice = 0;
  79. int32 item_choice = 0;
  80. int32 rare_choice = 0;
  81. int8 harvest_type = 0;
  82. int32 item_harvested = 0;
  83. int8 reward_total = 1;
  84. int32 rare_harvested = 0;
  85. int8 rare_item = 0;
  86. bool is_collection = false;
  87. if (!groundspawn_entries || !groundspawn_items) {
  88. LogWrite(GROUNDSPAWN__ERROR, 3, "GSpawn", "No groundspawn entries or items assigned to groundspawn id: %u", groundspawn_id);
  89. client->Message(CHANNEL_COLOR_RED, "Error: There are no groundspawn entries or items assigned to groundspawn id: %u", groundspawn_id);
  90. MHarvest.unlock();
  91. return;
  92. }
  93. if (number_harvests == 0) {
  94. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Total harvests depleated for groundspawn id: %u", groundspawn_id);
  95. client->SimpleMessage(CHANNEL_COLOR_RED, "Error: This spawn has nothing more to harvest!");
  96. MHarvest.unlock();
  97. return;
  98. }
  99. Skill* skill = 0;
  100. if (collection_skill == "Collecting") {
  101. skill = client->GetPlayer()->GetSkillByName("Gathering");
  102. is_collection = true;
  103. }
  104. else
  105. skill = client->GetPlayer()->GetSkillByName(collection_skill.c_str()); // Fix: #576 - don't skill up yet with GetSkillByName(skill, true), we might be trying to harvest low level
  106. if (!skill) {
  107. LogWrite(GROUNDSPAWN__WARNING, 3, "GSpawn", "Player '%s' lacks the skill: '%s'", client->GetPlayer()->GetName(), collection_skill.c_str());
  108. client->Message(CHANNEL_COLOR_RED, "Error: You do not have the '%s' skill!", collection_skill.c_str());
  109. MHarvest.unlock();
  110. return;
  111. }
  112. int16 totalSkill = skill->current_val;
  113. int32 skillID = master_item_list.GetItemStatIDByName(collection_skill);
  114. int16 max_skill_req_groundspawn = rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, MinSkillMultiplierValue)->GetInt16();
  115. if(max_skill_req_groundspawn < 1) // can't be 0
  116. max_skill_req_groundspawn = 1;
  117. if(skillID != 0xFFFFFFFF)
  118. {
  119. ((Entity*)client->GetPlayer())->MStats.lock();
  120. totalSkill += ((Entity*)client->GetPlayer())->stats[skillID];
  121. ((Entity*)client->GetPlayer())->MStats.unlock();
  122. }
  123. for (int8 i = 0; i < num_attempts_per_harvest; i++) {
  124. vector<GroundSpawnEntry*> mod_groundspawn_entries;
  125. if (groundspawn_entries) {
  126. vector<GroundSpawnEntry*> highest_match;
  127. vector<GroundSpawnEntry*>::iterator itr;
  128. GroundSpawnEntry* entry = 0; // current data
  129. GroundSpawnEntry* selected_table = 0; // selected table data
  130. // first, iterate through groundspawn_entries, discard tables player cannot use
  131. for (itr = groundspawn_entries->begin(); itr != groundspawn_entries->end(); itr++) {
  132. entry = *itr;
  133. if(entry->min_skill_level > max_skill_req_groundspawn)
  134. max_skill_req_groundspawn = entry->min_skill_level;
  135. // if player lacks skill, skip table
  136. if (entry->min_skill_level > totalSkill)
  137. continue;
  138. // if bonus, but player lacks level, skip table
  139. if (entry->bonus_table && (client->GetPlayer()->GetLevel() < entry->min_adventure_level))
  140. continue;
  141. // build modified entries table
  142. mod_groundspawn_entries.push_back(entry);
  143. LogWrite(GROUNDSPAWN__DEBUG, 5, "GSpawn", "Keeping groundspawn_entry: %i", entry->min_skill_level);
  144. }
  145. // if anything remains, find lowest min_skill_level in remaining set(s)
  146. if (mod_groundspawn_entries.size() > 0) {
  147. vector<GroundSpawnEntry*>::iterator itr;
  148. GroundSpawnEntry* entry = 0;
  149. for (itr = mod_groundspawn_entries.begin(); itr != mod_groundspawn_entries.end(); itr++) {
  150. entry = *itr;
  151. // find the low range of available tables for random roll
  152. if (lowest_skill_level > entry->min_skill_level || lowest_skill_level == 0)
  153. lowest_skill_level = entry->min_skill_level;
  154. }
  155. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Lowest Skill Level: %i", lowest_skill_level);
  156. }
  157. else {
  158. // if no tables chosen, you must lack the skills
  159. // TODO: move this check to LUA when harvest command is first selected
  160. client->Message(CHANNEL_COLOR_RED, "You lack the skills to harvest this node!");
  161. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "All groundspawn_entry tables tossed! No Skills? Something broke?");
  162. MHarvest.unlock();
  163. return;
  164. }
  165. // now roll to see which table to use
  166. table_choice = MakeRandomInt(lowest_skill_level, totalSkill);
  167. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Random INT for Table by skill level: %i", table_choice);
  168. int16 highest_score = 0;
  169. for (itr = mod_groundspawn_entries.begin(); itr != mod_groundspawn_entries.end(); itr++) {
  170. entry = *itr;
  171. // determines the highest min_skill_level in the current set of tables (if multiple tables)
  172. if (table_choice >= entry->min_skill_level && (highest_score == 0 || highest_score < table_choice)) {
  173. // removes old highest for the new one
  174. highest_match.clear();
  175. highest_score = entry->min_skill_level;
  176. }
  177. // if the score = level, push into highest_match set
  178. if (highest_score == entry->min_skill_level)
  179. highest_match.push_back(entry);
  180. }
  181. // if there is STILL more than 1 table player qualifies for, rand() and pick one
  182. if (highest_match.size() > 1) {
  183. int16 rand_index = rand() % highest_match.size();
  184. selected_table = highest_match.at(rand_index);
  185. }
  186. else if (highest_match.size() > 0)
  187. selected_table = highest_match.at(0);
  188. // by this point, we should have 1 table who's min skill matches the score (selected_table)
  189. if (selected_table) {
  190. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Using Table: %i, %i, %i, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %i",
  191. selected_table->min_skill_level,
  192. selected_table->min_adventure_level,
  193. selected_table->bonus_table,
  194. selected_table->harvest1,
  195. selected_table->harvest3,
  196. selected_table->harvest5,
  197. selected_table->harvest_imbue,
  198. selected_table->harvest_rare,
  199. selected_table->harvest10,
  200. selected_table->harvest_coin);
  201. // roll 1-100 for chance-to-harvest percentage
  202. float chance = MakeRandomFloat(0, 100);
  203. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Random FLOAT for harvest percentages: %.2f", chance);
  204. // starting with the lowest %, select a harvest type + reward qty
  205. if (chance <= selected_table->harvest10 && is_collection == false) {
  206. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Harvest 10 items + Rare Item from table : %i", selected_table->min_skill_level);
  207. harvest_type = 6;
  208. reward_total = 10;
  209. }
  210. else if (chance <= selected_table->harvest_rare && is_collection == false) {
  211. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Harvest Rare Item from table : %i", selected_table->min_skill_level);
  212. harvest_type = 5;
  213. }
  214. else if (chance <= selected_table->harvest_imbue && is_collection == false) {
  215. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Harvest Imbue Item from table : %i", selected_table->min_skill_level);
  216. harvest_type = 4;
  217. }
  218. else if (chance <= selected_table->harvest5 && is_collection == false) {
  219. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Harvest 5 Items from table : %i", selected_table->min_skill_level);
  220. harvest_type = 3;
  221. reward_total = 5;
  222. }
  223. else if (chance <= selected_table->harvest3 && is_collection == false) {
  224. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Harvest 3 Items from table : %i", selected_table->min_skill_level);
  225. harvest_type = 2;
  226. reward_total = 3;
  227. }
  228. else if (chance <= selected_table->harvest1 || totalSkill >= skill->max_val || is_collection) {
  229. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Harvest 1 Item from table : %i", selected_table->min_skill_level);
  230. harvest_type = 1;
  231. }
  232. else
  233. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Harvest nothing...");
  234. float node_maxskill_multiplier = rule_manager.GetZoneRule(client->GetCurrentZoneID(), R_Player, HarvestSkillUpMultiplier)->GetFloat();
  235. if(node_maxskill_multiplier <= 0.0f) {
  236. node_maxskill_multiplier = 1.0f;
  237. }
  238. int16 skillup_max_skill_allowed = (int16)((float)max_skill_req_groundspawn*node_maxskill_multiplier);
  239. if (!is_collection && skill && skill->current_val < skillup_max_skill_allowed) {
  240. skill = client->GetPlayer()->GetSkillByName(collection_skill.c_str(), true); // Fix: #576 - skill up after min skill and adv level checks
  241. }
  242. }
  243. // once you know how many and what type of item to harvest, pick an item from the list
  244. if (harvest_type) {
  245. vector<GroundSpawnEntryItem*> mod_groundspawn_items;
  246. vector<GroundSpawnEntryItem*> mod_groundspawn_rares;
  247. vector<GroundSpawnEntryItem*> mod_groundspawn_imbue;
  248. vector<GroundSpawnEntryItem*>::iterator itr;
  249. GroundSpawnEntryItem* entry = 0;
  250. // iterate through groundspawn_items, discard items player cannot roll for
  251. for (itr = groundspawn_items->begin(); itr != groundspawn_items->end(); itr++) {
  252. entry = *itr;
  253. // if this is a Rare, or an Imbue, but is_rare flag is 0, skip item
  254. if ((harvest_type == 5 || harvest_type == 4) && entry->is_rare == 0)
  255. continue;
  256. // if it is a 1, 3, or 5 and is_rare = 1, skip
  257. else if (harvest_type < 4 && entry->is_rare == 1)
  258. continue;
  259. // if the grid_id on the item matches player grid, or is 0, keep the item
  260. if (!entry->grid_id || (entry->grid_id == client->GetPlayer()->GetLocation())) {
  261. // build modified entries table
  262. if ((entry->is_rare == 1 && harvest_type == 5) || (entry->is_rare == 1 && harvest_type == 6)) {
  263. // if the matching item is rare, or harvest10 push to mod rares
  264. mod_groundspawn_rares.push_back(entry);
  265. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Keeping groundspawn_rare_item: %u", entry->item_id);
  266. }
  267. if (entry->is_rare == 0 && harvest_type != 4 && harvest_type != 5) {
  268. // if the matching item is normal,or harvest 10 push to mod items
  269. mod_groundspawn_items.push_back(entry);
  270. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Keeping groundspawn_common_item: %u", entry->item_id);
  271. }
  272. if (entry->is_rare == 2 && harvest_type == 4) {
  273. // if the matching item is imbue item, push to mod imbue
  274. mod_groundspawn_imbue.push_back(entry);
  275. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Keeping groundspawn_imbue_item: %u", entry->item_id);
  276. }
  277. }
  278. }
  279. // if any items remain in the list, random to see which one gets awarded
  280. if (mod_groundspawn_items.size() > 0) {
  281. // roll to see which item index to use
  282. item_choice = rand() % mod_groundspawn_items.size();
  283. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Random INT for which item to award: %i", item_choice);
  284. // set item_id to be awarded
  285. item_harvested = mod_groundspawn_items[item_choice]->item_id;
  286. // if reward is rare, set flag
  287. rare_item = mod_groundspawn_items[item_choice]->is_rare;
  288. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Item ID to award: %u, Rare = %i", item_harvested, item_rare);
  289. // if 10+rare, handle additional "rare" reward
  290. if (harvest_type == 6) {
  291. // make sure there is a rare table to choose from!
  292. if (mod_groundspawn_rares.size() > 0) {
  293. // roll to see which rare index to use
  294. rare_choice = rand() % mod_groundspawn_rares.size();
  295. // set (rare) item_id to be awarded
  296. rare_harvested = mod_groundspawn_rares[rare_choice]->item_id;
  297. // we're picking a rare here, so obviously this is true ;)
  298. rare_item = 1;
  299. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "RARE Item ID to award: %u", rare_harvested);
  300. }
  301. else {
  302. // all rare entries were eliminated above, or none are assigned. Either way, shouldn't be here!
  303. LogWrite(GROUNDSPAWN__ERROR, 3, "GSpawn", "Groundspawn Entry for '%s' (%i) has no RARE items!", GetName(), GetID());
  304. }
  305. }
  306. }
  307. else if (mod_groundspawn_rares.size() > 0) {
  308. // roll to see which rare index to use
  309. item_choice = rand() % mod_groundspawn_rares.size();
  310. // set (rare) item_id to be awarded
  311. item_harvested = mod_groundspawn_rares[item_choice]->item_id;
  312. // we're picking a rare here, so obviously this is true ;)
  313. rare_item = 1;
  314. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "RARE Item ID to award: %u", rare_harvested);
  315. }
  316. else if (mod_groundspawn_imbue.size() > 0) {
  317. // roll to see which rare index to use
  318. item_choice = rand() % mod_groundspawn_imbue.size();
  319. // set (rare) item_id to be awarded
  320. item_harvested = mod_groundspawn_imbue[item_choice]->item_id;
  321. // we're picking a rare here, so obviously this is true ;)
  322. rare_item = 0;
  323. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "imbue Item ID to award: %u", rare_harvested);
  324. }
  325. else {
  326. // all item entries were eliminated above, or none are assigned. Either way, shouldn't be here!
  327. LogWrite(GROUNDSPAWN__ERROR, 0, "GSpawn", "Groundspawn Entry for '%s' (%i) has no items!", GetName(), GetID());
  328. }
  329. // if an item was harvested, send updates to client, add item to inventory
  330. if (item_harvested) {
  331. char tmp[200] = { 0 };
  332. // set Normal item harvested
  333. master_item = master_item_list.GetItem(item_harvested);
  334. if (master_item) {
  335. // set details of Normal item
  336. item = new Item(master_item);
  337. // set how many of this item the player receives
  338. item->details.count = reward_total;
  339. // chat box update for normal item (todo: verify output text)
  340. client->Message(CHANNEL_HARVESTING, "You %s %i %s from the %s.", GetHarvestMessageName(true).c_str(), item->details.count, item->CreateItemLink(client->GetVersion(), true).c_str(), GetName());
  341. // add Normal item to player inventory
  342. bool itemDeleted = false;
  343. client->AddItem(item, &itemDeleted);
  344. if(!itemDeleted) {
  345. //Check if the player has a harvesting quest for this
  346. client->GetPlayer()->CheckQuestsHarvestUpdate(item, reward_total);
  347. // if this is a 10+rare, handle sepErately
  348. if (harvest_type == 6 && rare_item == 1) {
  349. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Item ID %u is Normal. Qty %i", item_harvested, item->details.count);
  350. // send Normal harvest message to client
  351. sprintf(tmp, "\\#64FFFFYou have %s:\12\\#C8FFFF%i %s", GetHarvestMessageName().c_str(), item->details.count, item->name.c_str());
  352. client->SendPopupMessage(10, tmp, "ui_harvested_normal", 2.25, 0xFF, 0xFF, 0xFF);
  353. client->GetPlayer()->UpdatePlayerStatistic(STAT_PLAYER_ITEMS_HARVESTED, item->details.count);
  354. // set Rare item harvested
  355. master_rare = master_item_list.GetItem(rare_harvested);
  356. if (master_rare) {
  357. // set details of Rare item
  358. item_rare = new Item(master_rare);
  359. // count of Rare is always 1
  360. item_rare->details.count = 1;
  361. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Item ID %u is RARE!", rare_harvested);
  362. // send Rare harvest message to client
  363. sprintf(tmp, "\\#FFFF6ERare item found!\12%s: \\#C8FFFF%i %s", GetHarvestMessageName().c_str(), item_rare->details.count, item_rare->name.c_str());
  364. client->Message(CHANNEL_HARVESTING, "You have found a rare item!");
  365. client->SendPopupMessage(11, tmp, "ui_harvested_rare", 2.25, 0xFF, 0xFF, 0xFF);
  366. client->GetPlayer()->UpdatePlayerStatistic(STAT_PLAYER_RARES_HARVESTED, item_rare->details.count);
  367. // chat box update for rare item (todo: verify output text)
  368. client->Message(CHANNEL_HARVESTING, "You %s %i %s from the %s.", GetHarvestMessageName(true).c_str(), item_rare->details.count, item->CreateItemLink(client->GetVersion(), true).c_str(), GetName());
  369. // add Rare item to player inventory
  370. client->AddItem(item_rare);
  371. //Check if the player has a harvesting quest for this
  372. client->GetPlayer()->CheckQuestsHarvestUpdate(item_rare, 1);
  373. }
  374. }
  375. else if (rare_item == 1) {
  376. // if harvest signaled rare or imbue type
  377. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Item ID %u is RARE! Qty: %i", item_harvested, item->details.count);
  378. // send Rare harvest message to client
  379. sprintf(tmp, "\\#FFFF6ERare item found!\12%s: \\#C8FFFF%i %s", GetHarvestMessageName().c_str(), item->details.count, item->name.c_str());
  380. client->Message(CHANNEL_HARVESTING, "You have found a rare item!");
  381. client->SendPopupMessage(11, tmp, "ui_harvested_rare", 2.25, 0xFF, 0xFF, 0xFF);
  382. client->GetPlayer()->UpdatePlayerStatistic(STAT_PLAYER_RARES_HARVESTED, item->details.count);
  383. }
  384. else {
  385. // send Normal harvest message to client
  386. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "Item ID %u is Normal. Qty %i", item_harvested, item->details.count);
  387. sprintf(tmp, "\\#64FFFFYou have %s:\12\\#C8FFFF%i %s", GetHarvestMessageName().c_str(), item->details.count, item->name.c_str());
  388. client->SendPopupMessage(10, tmp, "ui_harvested_normal", 2.25, 0xFF, 0xFF, 0xFF);
  389. client->GetPlayer()->UpdatePlayerStatistic(STAT_PLAYER_ITEMS_HARVESTED, item->details.count);
  390. }
  391. }
  392. }
  393. else {
  394. // error!
  395. LogWrite(GROUNDSPAWN__ERROR, 0, "GSpawn", "Error: Item ID Not Found - %u", item_harvested);
  396. client->Message(CHANNEL_COLOR_RED, "Error: Unable to find item id %u", item_harvested);
  397. }
  398. // decrement # of pulls on this node before it despawns
  399. number_harvests--;
  400. }
  401. else {
  402. // if no item harvested
  403. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "No item_harvested");
  404. client->Message(CHANNEL_HARVESTING, "You failed to %s anything from %s.", GetHarvestMessageName(true, true).c_str(), GetName());
  405. }
  406. }
  407. else {
  408. // if no harvest type
  409. LogWrite(GROUNDSPAWN__DEBUG, 3, "GSpawn", "No harvest_type");
  410. client->Message(CHANNEL_HARVESTING, "You failed to %s anything from %s.", GetHarvestMessageName(true, true).c_str(), GetName());
  411. }
  412. }
  413. } // cycle through num_attempts_per_harvest
  414. MHarvest.unlock();
  415. LogWrite(GROUNDSPAWN__DEBUG, 0, "GSpawn", "Process harvest complete for player '%s' (%u)", client->GetPlayer()->GetName(), client->GetPlayer()->GetID());
  416. }
  417. string GroundSpawn::GetHarvestMessageName(bool present_tense, bool failure){
  418. string ret = "";
  419. if((collection_skill == "Gathering" ||collection_skill == "Collecting") && !present_tense)
  420. ret = "gathered";
  421. else if(collection_skill == "Gathering" || collection_skill == "Collecting")
  422. ret = "gather";
  423. else if(collection_skill == "Mining" && !present_tense)
  424. ret = "mined";
  425. else if(collection_skill == "Mining")
  426. ret = "mine";
  427. else if (collection_skill == "Fishing" && !present_tense)
  428. ret = "fished";
  429. else if(collection_skill == "Fishing")
  430. ret = "fish";
  431. else if(collection_skill == "Trapping" && !present_tense && !failure)
  432. ret = "acquired";
  433. else if(collection_skill == "Trapping" && failure)
  434. ret = "trap";
  435. else if(collection_skill == "Trapping")
  436. ret = "acquire";
  437. else if(collection_skill == "Foresting" && !present_tense)
  438. ret = "forested";
  439. else if(collection_skill == "Foresting")
  440. ret = "forest";
  441. else if (collection_skill == "Collecting")
  442. ret = "collect";
  443. return ret;
  444. }
  445. string GroundSpawn::GetHarvestSpellType(){
  446. string ret = "";
  447. if(collection_skill == "Gathering" || collection_skill == "Collecting")
  448. ret = "gather";
  449. else if(collection_skill == "Mining")
  450. ret = "mine";
  451. else if(collection_skill == "Trapping")
  452. ret = "trap";
  453. else if(collection_skill == "Foresting")
  454. ret = "chop";
  455. else if(collection_skill == "Fishing")
  456. ret = "fish";
  457. return ret;
  458. }
  459. string GroundSpawn::GetHarvestSpellName() {
  460. string ret = "";
  461. if (collection_skill == "Collecting")
  462. ret = "Gathering";
  463. else
  464. ret = collection_skill;
  465. return ret;
  466. }
  467. void GroundSpawn::HandleUse(Client* client, string type){
  468. if(!client || type.length() == 0)
  469. return;
  470. //The following check disables the use of the groundspawn if spawn access is not granted
  471. if (client) {
  472. bool meets_quest_reqs = MeetsSpawnAccessRequirements(client->GetPlayer());
  473. if (!meets_quest_reqs && (GetQuestsRequiredOverride() & 2) == 0)
  474. return;
  475. else if (meets_quest_reqs && appearance.show_command_icon != 1)
  476. return;
  477. }
  478. MHarvestUse.lock();
  479. if (type == GetHarvestSpellType() && MeetsSpawnAccessRequirements(client->GetPlayer())) {
  480. Spell* spell = master_spell_list.GetSpellByName(GetHarvestSpellName().c_str());
  481. if (spell)
  482. client->GetCurrentZone()->ProcessSpell(spell, client->GetPlayer(), client->GetPlayer()->GetTarget(), true, true);
  483. }
  484. else if (appearance.show_command_icon == 1 && MeetsSpawnAccessRequirements(client->GetPlayer())) {
  485. EntityCommand* entity_command = FindEntityCommand(type);
  486. if (entity_command)
  487. client->GetCurrentZone()->ProcessEntityCommand(entity_command, client->GetPlayer(), client->GetPlayer()->GetTarget());
  488. }
  489. MHarvestUse.unlock();
  490. }