PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/ZoneServer/ForageManager.cpp

http://github.com/swganh/mmoserver
C++ | 373 lines | 279 code | 53 blank | 41 comment | 58 complexity | 51ab425ae539c4cb5152e7c7e2e4d091 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. ---------------------------------------------------------------------------------------
  3. This source file is part of SWG:ANH (Star Wars Galaxies - A New Hope - Server Emulator)
  4. For more information, visit http://www.swganh.com
  5. Copyright (c) 2006 - 2010 The SWG:ANH Team
  6. ---------------------------------------------------------------------------------------
  7. Use of this source code is governed by the GPL v3 license that can be found
  8. in the COPYING file or at http://www.gnu.org/licenses/gpl-3.0.html
  9. This library is free software; you can redistribute it and/or
  10. modify it under the terms of the GNU Lesser General Public
  11. License as published by the Free Software Foundation; either
  12. version 2.1 of the License, or (at your option) any later version.
  13. This library is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. Lesser General Public License for more details.
  17. You should have received a copy of the GNU Lesser General Public
  18. License along with this library; if not, write to the Free Software
  19. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. ---------------------------------------------------------------------------------------
  21. */
  22. #include "ZoneServer/ForageManager.h"
  23. #include <list>
  24. #include "MathLib/Rectangle.h"
  25. #include "MessageLib/MessageLib.h"
  26. #include "ZoneServer/MedicManager.h"
  27. #include "ZoneServer/PlayerObject.h"
  28. #include "ZoneServer/ScoutManager.h"
  29. #include "ZoneServer/WorldManager.h"
  30. ForageManager* ForageManager::mSingleton = NULL;
  31. ForageManager::ForageManager()
  32. {
  33. pHead = NULL;
  34. }
  35. //================================================================================
  36. //FORAGING!
  37. //================================================================================
  38. class ForageAttempt
  39. {
  40. public:
  41. ForageAttempt(PlayerObject* player, uint64 time, forageClasses forageClass)
  42. {
  43. startTime = time;
  44. playerID = player->getId();
  45. completed = false;
  46. mForageClass = forageClass;
  47. orig_x = player->mPosition.x;
  48. orig_y = player->mPosition.y;
  49. orig_z = player->mPosition.z;
  50. }
  51. uint64 startTime;
  52. uint64 playerID;
  53. forageClasses mForageClass;
  54. bool completed;
  55. float orig_x;
  56. float orig_y;
  57. float orig_z;
  58. };
  59. class ForagePocket
  60. {
  61. public:
  62. ForagePocket(PlayerObject* player)
  63. {
  64. innerRect = Anh_Math::Rectangle(player->mPosition.x - 10,player->mPosition.z - 10,20,20);
  65. outterRect = Anh_Math::Rectangle(player->mPosition.x - 30,player->mPosition.z - 30,60,60);
  66. pNext = NULL;
  67. }
  68. ~ForagePocket()
  69. {
  70. //This shouldn't be a problem, but it's here just in case.
  71. for(std::list<ForageAttempt*>::iterator it=attempts.begin(); it != attempts.end();)
  72. {
  73. delete (*it);
  74. it=attempts.erase(it);
  75. }
  76. }
  77. bool containsPlayer(PlayerObject* player)
  78. {
  79. if((outterRect.getPosition().x > player->mPosition.x) && ((outterRect.getPosition().x + outterRect.getWidth()) < player->mPosition.x))
  80. {
  81. if((outterRect.getPosition().z > player->mPosition.z) && ((outterRect.getPosition().z + outterRect.getHeight()) < player->mPosition.z))
  82. return true;
  83. else
  84. return false;
  85. }
  86. else
  87. return false;
  88. }
  89. void addAttempt(ForageAttempt* attempt)
  90. {
  91. attempts.push_back(attempt);
  92. }
  93. bool updateAttempts(uint64 currentTime); //if True Delete this Pocket, if False don't
  94. ForagePocket* pNext;
  95. Anh_Math::Rectangle outterRect;
  96. private:
  97. std::list<ForageAttempt*> attempts;
  98. Anh_Math::Rectangle innerRect;
  99. };
  100. void ForageManager::startForage(PlayerObject* player, forageClasses forageClass)
  101. {
  102. //Check for Inside building
  103. if(player->getParentId() != 0)
  104. {
  105. gForageManager->failForage(player, NOT_OUTSIDE);
  106. return;
  107. }
  108. //Check for combat
  109. if(player->states.checkState(CreatureState_Combat))
  110. {
  111. gForageManager->failForage(player, IN_COMBAT);
  112. return;
  113. }
  114. //Check for action being too low
  115. if(player->getHam()->mAction.getCurrentHitPoints() < 101)
  116. {
  117. gForageManager->failForage(player, ACTION_LOW);
  118. return;
  119. }
  120. //Check for skill being too low
  121. if(forageClass == ForageClass_Scout && !player->checkSkill(45)) //Scout -> Survival 1
  122. {
  123. gForageManager->failForage(player, NO_SKILL);
  124. return;
  125. }
  126. else if(forageClass == ForageClass_Medic && !player->checkSkill(51))
  127. {
  128. gForageManager->failForage(player, NO_SKILL);
  129. return;
  130. }
  131. //Already foraging
  132. if(player->isForaging())
  133. {
  134. gForageManager->failForage(player, ALREADY_FORAGING);
  135. return;
  136. }
  137. player->setForaging(true);
  138. //Starts the Foraging Animation
  139. gMessageLib->sendCreatureAnimation(player, std::string("forage"));
  140. //Use up some action!
  141. player->getHam()->updatePropertyValue(HamBar_Action,HamProperty_CurrentHitpoints, -100);
  142. //Creates a ForageAttempt object for tracking the forage operation
  143. ForageAttempt* attempt = new ForageAttempt(player, gWorldManager->GetCurrentGlobalTick(), forageClass);
  144. //FIND THE APPROPRIATE FORAGEPocket
  145. ForagePocket* it = pHead;
  146. while(it != NULL)
  147. {
  148. if(it->containsPlayer(player))
  149. {
  150. it->addAttempt(attempt);
  151. return;
  152. }
  153. it = it->pNext;
  154. }
  155. //None of them contained the player. We need to make new one.
  156. ForagePocket* new_pocket = new ForagePocket(player);
  157. it = pHead;
  158. ForagePocket* previousHead = NULL;
  159. while(it != NULL)
  160. {
  161. previousHead = it;
  162. it = it->pNext;
  163. }
  164. if(previousHead == NULL)
  165. pHead = new_pocket;
  166. else
  167. previousHead->pNext = new_pocket;
  168. new_pocket->addAttempt(attempt);
  169. }
  170. void ForageManager::forageUpdate()
  171. {
  172. ForagePocket* it = pHead;
  173. ForagePocket* previousHead = NULL;
  174. while(it != NULL)
  175. {
  176. if(it->updateAttempts(gWorldManager->GetCurrentGlobalTick())) //If true we delete this Pocket
  177. {
  178. if(previousHead == NULL)
  179. {
  180. pHead = it->pNext;
  181. }
  182. else
  183. {
  184. previousHead->pNext = it->pNext;
  185. }
  186. delete it;
  187. it = previousHead;
  188. }
  189. if(it != NULL)
  190. it = it->pNext;
  191. }
  192. }
  193. void ForageManager::failForage(PlayerObject* player, forageFails fail)
  194. {
  195. if(!player || !player->isConnected())
  196. return;
  197. switch(fail)
  198. {
  199. case NOT_OUTSIDE:
  200. gMessageLib->SendSystemMessage(::common::OutOfBand("skl_use", "sys_forage_inside"), player);
  201. break;
  202. case PLAYER_MOVED:
  203. gMessageLib->SendSystemMessage(::common::OutOfBand("skl_use", "sys_forage_movefail"), player);
  204. break;
  205. case ACTION_LOW:
  206. gMessageLib->SendSystemMessage(::common::OutOfBand("skl_use", "sys_forage_attrib"), player);
  207. break;
  208. case IN_COMBAT:
  209. gMessageLib->SendSystemMessage(::common::OutOfBand("skl_use", "sys_forage_cant"), player);
  210. break;
  211. case AREA_EMPTY:
  212. gMessageLib->SendSystemMessage(::common::OutOfBand("skl_use", "sys_forage_empty"), player);
  213. break;
  214. case ENTERED_COMBAT:
  215. gMessageLib->SendSystemMessage(::common::OutOfBand("skl_use", "sys_forage_combatfail"), player);
  216. break;
  217. case NO_SKILL:
  218. gMessageLib->SendSystemMessage(::common::OutOfBand("skl_use", "sys_forage_noskill"), player);
  219. break;
  220. case ALREADY_FORAGING:
  221. gMessageLib->SendSystemMessage(::common::OutOfBand("skl_use", "sys_forage_already"), player);
  222. return;
  223. }
  224. player->setForaging(false);
  225. }
  226. bool ForagePocket::updateAttempts(uint64 currentTime)
  227. {
  228. if(attempts.empty())
  229. return true;
  230. std::list<ForageAttempt*>::iterator it = attempts.begin();
  231. unsigned int AttemptCount = 0;
  232. while(it != attempts.end())
  233. {
  234. if((currentTime - (*it)->startTime) >= 300000) //5minutes until we reopen the pocket
  235. {
  236. delete (*it);
  237. it = attempts.erase(it);
  238. AttemptCount--;
  239. }
  240. else if((currentTime - (*it)->startTime) >= 8000 && !(*it)->completed)
  241. {
  242. PlayerObject* player = (PlayerObject*)gWorldManager->getObjectById((*it)->playerID);
  243. if(player != NULL)
  244. {
  245. if(player->states.checkState(CreatureState_Combat))
  246. {
  247. ForageManager::failForage(player, ENTERED_COMBAT);
  248. (*it)->completed = true;
  249. it++;
  250. AttemptCount++;
  251. continue;
  252. }
  253. bool inIt = false;
  254. if((innerRect.getPosition().x > player->mPosition.x) && ((innerRect.getPosition().x + innerRect.getWidth()) < player->mPosition.x))
  255. {
  256. if((innerRect.getPosition().z > player->mPosition.z) && ((innerRect.getPosition().z + innerRect.getHeight()) < player->mPosition.z))
  257. {
  258. inIt = true;
  259. }
  260. }
  261. if(inIt && AttemptCount < 4)
  262. {
  263. //The player has a chance to get something
  264. ForageManager::successForage(player, (*it)->mForageClass);
  265. (*it)->completed = true;
  266. }
  267. else
  268. {
  269. ForageManager::failForage(player, AREA_EMPTY);
  270. (*it)->completed = true;
  271. }
  272. }
  273. AttemptCount++;
  274. it++;
  275. }
  276. else
  277. {
  278. PlayerObject* player = (PlayerObject*)gWorldManager->getObjectById((*it)->playerID);
  279. if(!(*it)->completed && player)
  280. {
  281. if(player->states.checkState(CreatureState_Combat))
  282. {
  283. ForageManager::failForage(player, ENTERED_COMBAT);
  284. (*it)->completed = true;
  285. }
  286. if(!(*it)->completed)
  287. {
  288. if((*it)->orig_x != player->mPosition.x || (*it)->orig_y != player->mPosition.y ||
  289. (*it)->orig_z != player->mPosition.z)
  290. {
  291. ForageManager::failForage(player, PLAYER_MOVED);
  292. (*it)->completed = true;
  293. }
  294. }
  295. }
  296. AttemptCount++;
  297. it++;
  298. }
  299. }
  300. return false;
  301. }
  302. void ForageManager::successForage(PlayerObject* player, forageClasses forageClass)
  303. {
  304. if(!player || player->isForaging() == false)
  305. return;
  306. switch(forageClass)
  307. {
  308. case ForageClass_Scout:
  309. gScoutManager->successForage(player);
  310. break;
  311. case ForageClass_Medic:
  312. gMedicManager->successForage(player);
  313. break;
  314. }
  315. }