Entity.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644
  1. #include "Entity.h"
  2. #include <Mat4.h>
  3. #include <Text.h>
  4. #include "BlockType.h"
  5. #include "Dimension.h"
  6. #include "EntityType.h"
  7. #include "Game.h"
  8. #include "ItemSkill.h"
  9. #include "ItemStack.h"
  10. #include "ItemType.h"
  11. #include "Quest.h"
  12. #include "UIMLBuilder.h"
  13. ActionTarget::ActionTarget(Framework::Vec3<int> blockPos, Direction blockSide)
  14. : blockPos(blockPos),
  15. targetBlockSide(blockSide),
  16. entityId(-1)
  17. {}
  18. ActionTarget::ActionTarget(int entityId)
  19. : entityId(entityId)
  20. {}
  21. bool ActionTarget::isBlock(
  22. Framework::Vec3<int> blockPos, Direction blockSide) const
  23. {
  24. return this->entityId == -1 && this->blockPos == blockPos
  25. && (this->targetBlockSide == blockSide || blockSide == NO_DIRECTION);
  26. }
  27. bool ActionTarget::isEntity(int entityId) const
  28. {
  29. return this->entityId == entityId;
  30. }
  31. bool ActionTarget::useItemSkillOnTarget(
  32. Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem)
  33. {
  34. if (entityId >= 0)
  35. {
  36. Entity* target = Game::INSTANCE->zEntity(entityId);
  37. if (target)
  38. {
  39. return zItemSkill->use(zActor, zUsedItem, target);
  40. }
  41. }
  42. else
  43. {
  44. Block* block = Game::INSTANCE->zRealBlockInstance(
  45. blockPos, zActor->getDimensionId());
  46. if (block)
  47. {
  48. return zItemSkill->use(zActor, zUsedItem, block);
  49. }
  50. }
  51. return 0;
  52. }
  53. bool ActionTarget::interactItemSkillOnTarget(
  54. Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem)
  55. {
  56. if (zItemSkill)
  57. {
  58. if (entityId >= 0)
  59. {
  60. Entity* target = Game::INSTANCE->zEntity(entityId);
  61. if (target) return zItemSkill->interact(zActor, zUsedItem, target);
  62. }
  63. else
  64. {
  65. Block* block = Game::INSTANCE->zRealBlockInstance(
  66. blockPos, zActor->getDimensionId());
  67. if (block) return zItemSkill->interact(zActor, zUsedItem, block);
  68. }
  69. }
  70. else
  71. {
  72. bool itemChanged = 0;
  73. if (entityId >= 0)
  74. {
  75. Block* block = Game::INSTANCE->zRealBlockInstance(
  76. blockPos, zActor->getDimensionId());
  77. if (block) block->interact(zUsedItem, zActor, itemChanged);
  78. }
  79. else
  80. {
  81. Block* block = Game::INSTANCE->zRealBlockInstance(
  82. blockPos, zActor->getDimensionId());
  83. if (block) block->interact(zUsedItem, zActor, itemChanged);
  84. }
  85. return itemChanged;
  86. }
  87. return 0;
  88. }
  89. bool ActionTarget::placeBlock(Entity* zActor, Item* zItem)
  90. {
  91. if (zActor->getStamina() > 0.2f)
  92. {
  93. if (zItem->canBePlacedAt(zActor->getDimensionId(),
  94. blockPos + getDirection(targetBlockSide)))
  95. {
  96. Block* block = zItem->zPlacedBlockType()->createBlockAt(
  97. blockPos + getDirection(targetBlockSide),
  98. zActor->getDimensionId(),
  99. zItem);
  100. if (block)
  101. {
  102. Game::INSTANCE->zQuestManager()->processEvent(
  103. new QuestEventBlockPlace(
  104. zActor ? dynamic_cast<Entity*>(zActor->getThis()) : 0,
  105. block->zBlockType()->getId()));
  106. Game::INSTANCE->zDimension(zActor->getDimensionId())
  107. ->placeBlock(block->getPos(), block);
  108. zItem->onPlaced();
  109. zActor->setStamina(zActor->getStamina() - 0.2f);
  110. return 1;
  111. }
  112. }
  113. }
  114. return 0;
  115. }
  116. void ActionTarget::toMessage(
  117. const ActionTarget* zTarget, int dimensionId, NetworkMessage* zMsg)
  118. {
  119. if (zTarget)
  120. {
  121. if (zTarget->entityId >= 0)
  122. {
  123. Entity* zEntity = Game::INSTANCE->zEntity(zTarget->entityId);
  124. if (zEntity)
  125. {
  126. Framework::XML::Element* targetUIML = zEntity->getTargetUIML();
  127. Framework::Text targetUIMLText
  128. = targetUIML ? targetUIML->toString() : Framework::Text();
  129. targetUIML->release();
  130. char* message = new char[8 + targetUIMLText.getLength()];
  131. message[0] = 3;
  132. message[1] = 1;
  133. *(int*)(message + 2) = zTarget->entityId;
  134. *(short*)(message + 6) = (short)targetUIMLText.getLength();
  135. memcpy(message + 8,
  136. targetUIMLText.getText(),
  137. targetUIMLText.getLength());
  138. zMsg->setMessage(message, 8 + targetUIMLText.getLength());
  139. }
  140. else
  141. {
  142. char* message = new char[2];
  143. message[0] = 3;
  144. message[1] = 0;
  145. zMsg->setMessage(message, 2);
  146. }
  147. }
  148. else
  149. {
  150. Framework::XML::Element* targetUIML = 0;
  151. auto block
  152. = Game::INSTANCE->zBlockAt(zTarget->blockPos, dimensionId, 0);
  153. if (block.isA())
  154. {
  155. targetUIML = block.getA()->getTargetUIML();
  156. }
  157. else if (block.isB())
  158. {
  159. targetUIML
  160. = Game::INSTANCE->zBlockType(block.getB())->getTargetUIML();
  161. }
  162. Framework::Text targetUIMLText
  163. = targetUIML ? targetUIML->toString() : Framework::Text();
  164. char* message = new char[15 + targetUIMLText.getLength() + 2];
  165. message[0] = 3;
  166. message[1] = 2;
  167. *(int*)(message + 2) = zTarget->blockPos.x;
  168. *(int*)(message + 6) = zTarget->blockPos.y;
  169. *(int*)(message + 10) = zTarget->blockPos.z;
  170. *(message + 14) = zTarget->targetBlockSide;
  171. short len = (short)targetUIMLText.getLength();
  172. *(short*)(message + 15) = len;
  173. memcpy(message + 17, targetUIMLText.getText(), len);
  174. zMsg->setMessage(message, 15 + len + 2);
  175. }
  176. }
  177. else
  178. {
  179. char* message = new char[2];
  180. message[0] = 3;
  181. message[1] = 0;
  182. zMsg->setMessage(message, 2);
  183. }
  184. }
  185. void ActionTarget::save(ActionTarget* zTarget, Framework::StreamWriter* zWriter)
  186. {
  187. if (zTarget)
  188. {
  189. if (zTarget->entityId >= 0)
  190. {
  191. char b = 1;
  192. zWriter->write(&b, 1);
  193. zWriter->write((char*)&zTarget->entityId, 4);
  194. }
  195. else
  196. {
  197. char b = 2;
  198. zWriter->write(&b, 1);
  199. zWriter->write((char*)&zTarget->blockPos.x, 4);
  200. zWriter->write((char*)&zTarget->blockPos.y, 4);
  201. zWriter->write((char*)&zTarget->blockPos.z, 4);
  202. zWriter->write((char*)&zTarget->targetBlockSide, 1);
  203. }
  204. }
  205. else
  206. {
  207. char b = 0;
  208. zWriter->write(&b, 1);
  209. }
  210. }
  211. ActionTarget* ActionTarget::load(Framework::StreamReader* zReader)
  212. {
  213. char b;
  214. zReader->read(&b, 1);
  215. if (b == 1)
  216. {
  217. int id;
  218. zReader->read((char*)&id, 4);
  219. return new ActionTarget(id);
  220. }
  221. else if (b == 2)
  222. {
  223. Framework::Vec3<int> pos;
  224. Direction side;
  225. zReader->read((char*)&pos.x, 4);
  226. zReader->read((char*)&pos.y, 4);
  227. zReader->read((char*)&pos.z, 4);
  228. zReader->read((char*)&side, 1);
  229. return new ActionTarget(pos, side);
  230. }
  231. return 0;
  232. }
  233. Entity::Entity(
  234. int typeId, Framework::Vec3<float> location, int dimensionId, int entityId)
  235. : Inventory(location, dimensionId, true),
  236. stamina(1.f),
  237. hunger(1.f),
  238. currentHP(1.f),
  239. thirst(1.f),
  240. chatSecurityLevel(0),
  241. lastChunkCenter(0, 0),
  242. lastSavedChunkCenter(Framework::Maybe<Framework::Point>::empty()),
  243. lastDimensionId(-1),
  244. maxHP(1.f),
  245. maxStamina(1.f),
  246. maxHunger(1.f),
  247. maxThirst(1.f),
  248. targetDistanceLimit(0.f),
  249. maxMovementSpeed(0.f),
  250. speed(0, 0, 0),
  251. faceDir(1, 0, 0),
  252. target(0),
  253. typeId(typeId),
  254. removed(0),
  255. gravityMultiplier(1.f),
  256. jumpSpeed(0.f),
  257. id(entityId),
  258. placeBlockCooldown(0.0),
  259. rotation(0.f),
  260. movementFlags(0),
  261. collisionMap(0),
  262. collisionMapLength(0)
  263. {
  264. registerAfterPushStackCall(
  265. [this](ItemSlot* zSlot, Direction dir, const Item* zItem, int count) {
  266. if (count > 0)
  267. {
  268. Game::INSTANCE->zQuestManager()->processEvent(
  269. new QuestEventItemPickup(dynamic_cast<Entity*>(getThis()),
  270. zItem->getTypeId(),
  271. count));
  272. }
  273. });
  274. }
  275. void Entity::onDeath(Entity* zActor, Item* zUsedItem, ItemSkill* zUsedSkill)
  276. {
  277. if (!removed)
  278. {
  279. for (DropConfig* config : zType()->getDropConfigs())
  280. {
  281. config->onObjectDestroyed(zActor, zUsedItem, zUsedSkill, this);
  282. }
  283. Dimension* dim = Game::INSTANCE->zDimension(dimensionId);
  284. if (dim)
  285. {
  286. Chunk* chunk = dim->zChunk(lastChunkCenter);
  287. if (chunk)
  288. {
  289. chunk->onEntityLeaves(this, 0);
  290. }
  291. dim->removeEntity(id);
  292. }
  293. removed = 1;
  294. }
  295. }
  296. bool Entity::useItem(int typeId, ItemStack* zStack, bool left)
  297. {
  298. if (left)
  299. {
  300. if (!zStack || !zStack->zItem() || zStack->zItem()->isUsable())
  301. {
  302. cs.lock();
  303. if (target)
  304. {
  305. ItemSkill* selected = zSkill(typeId);
  306. if (!selected)
  307. {
  308. selected = Game::INSTANCE->zItemType(typeId)
  309. ->createDefaultItemSkill();
  310. selected->setItemTypeId(typeId);
  311. if (selected) skills.add(selected);
  312. }
  313. if (!selected)
  314. {
  315. selected = zSkill(ItemTypeEnum::PLAYER_HAND);
  316. selected->setItemTypeId(ItemTypeEnum::PLAYER_HAND);
  317. }
  318. bool result = target->useItemSkillOnTarget(this,
  319. selected,
  320. !zStack || zStack->getSize() > 1 ? 0
  321. : (Item*)zStack->zItem());
  322. cs.unlock();
  323. return result;
  324. }
  325. cs.unlock();
  326. }
  327. else
  328. {
  329. useItem(ItemTypeEnum::PLAYER_HAND, 0, left);
  330. }
  331. }
  332. else
  333. {
  334. if (zStack && zStack->zItem() && zStack->zItem()->isPlaceable()
  335. && zStack->getSize() > 0)
  336. { // place item
  337. cs.lock();
  338. if (target)
  339. {
  340. if (placeBlockCooldown <= 0)
  341. {
  342. Item* item = zStack->extractFromStack();
  343. bool result = target->placeBlock(this, item);
  344. if (item->getHp() > 0)
  345. {
  346. if (!zStack->addToStack(
  347. dynamic_cast<Item*>(item->getThis())))
  348. {
  349. ItemStack* newStack = new ItemStack(item, 1);
  350. addItems(newStack, NO_DIRECTION, 0);
  351. if (newStack->getSize())
  352. {
  353. Game::INSTANCE->spawnItem(
  354. location, dimensionId, newStack);
  355. }
  356. }
  357. else
  358. {
  359. item->release();
  360. }
  361. }
  362. else
  363. {
  364. item->release();
  365. }
  366. if (result)
  367. {
  368. placeBlockCooldown = 1.0;
  369. }
  370. cs.unlock();
  371. return result;
  372. }
  373. else
  374. {
  375. cs.unlock();
  376. return 0;
  377. }
  378. }
  379. cs.unlock();
  380. }
  381. if (zStack && zStack->zItem() && zStack->zItem()->isEatable()
  382. && zStack->getSize() > 0)
  383. { // eat item
  384. if (zStack->getSize() == 1)
  385. {
  386. return ((Item*)zStack->zItem())->applyFoodEffects(this);
  387. }
  388. else
  389. {
  390. if (zStack->zItem()->canApplyFoodEffectsFully(this))
  391. {
  392. Item* item = zStack->extractFromStack();
  393. item->applyFoodEffects(this);
  394. item->release();
  395. return 1;
  396. }
  397. }
  398. }
  399. if (!zStack || !zStack->zItem() || zStack->zItem()->isUsable())
  400. {
  401. cs.lock();
  402. if (target)
  403. {
  404. ItemSkill* selected = zSkill(typeId);
  405. if (!selected)
  406. {
  407. selected = Game::INSTANCE->zItemType(typeId)
  408. ->createDefaultItemSkill();
  409. selected->setItemTypeId(typeId);
  410. if (selected) skills.add(selected);
  411. }
  412. if (!selected)
  413. {
  414. selected = zSkill(ItemTypeEnum::PLAYER_HAND);
  415. selected->setItemTypeId(ItemTypeEnum::PLAYER_HAND);
  416. }
  417. bool result = target->interactItemSkillOnTarget(this,
  418. selected,
  419. !zStack || zStack->getSize() > 1 ? 0
  420. : (Item*)zStack->zItem());
  421. cs.unlock();
  422. return result;
  423. }
  424. cs.unlock();
  425. }
  426. else
  427. {
  428. useItem(ItemTypeEnum::PLAYER_HAND, 0, left);
  429. }
  430. }
  431. return 0;
  432. }
  433. void Entity::onTargetChange() {}
  434. bool Entity::interact(Item* zItem, Entity* zActor)
  435. {
  436. return false;
  437. }
  438. void Entity::calculateTarget(const Item* zItem)
  439. {
  440. Framework::Vec3<float> headPosition = location + faceOffset;
  441. int px = (int)floor(headPosition.x);
  442. int py = (int)floor(headPosition.y);
  443. int pz = (int)floor(headPosition.z);
  444. Framework::Vec3<float> direction = faceDir;
  445. direction.normalize();
  446. Direction dir = BOTTOM;
  447. bool found = false;
  448. bool changed = false;
  449. while (true)
  450. {
  451. if (getDefaultBlock(
  452. Game::INSTANCE->zBlockAt(
  453. Framework::Vec3<int>{px, py, pz}, dimensionId, 0))
  454. ->isInteractable(zItem))
  455. {
  456. found = true;
  457. if (!target || !target->isBlock({px, py, pz}, dir))
  458. {
  459. changed = true;
  460. }
  461. break;
  462. }
  463. // collision to neighbor of current block
  464. if (direction.x > 0)
  465. {
  466. float xt = ((float)px + 1.f - headPosition.x) / direction.x;
  467. Framework::Vec3<float> tmp = headPosition + direction * xt;
  468. if (xt <= targetDistanceLimit && tmp.y >= (float)py
  469. && tmp.y < (float)py + 1.f && tmp.z >= (float)pz
  470. && tmp.z < (float)pz + 1.f)
  471. {
  472. dir = WEST;
  473. px++;
  474. continue;
  475. }
  476. }
  477. if (direction.x < 0)
  478. {
  479. float xt = ((float)px - headPosition.x) / direction.x;
  480. Framework::Vec3<float> tmp = headPosition + direction * xt;
  481. if (xt <= targetDistanceLimit && tmp.y >= (float)py
  482. && tmp.y < (float)py + 1.f && tmp.z >= (float)pz
  483. && tmp.z < (float)pz + 1.f)
  484. {
  485. dir = EAST;
  486. px--;
  487. continue;
  488. }
  489. }
  490. if (direction.y > 0)
  491. {
  492. float yt = ((float)py + 1.f - headPosition.y) / direction.y;
  493. Framework::Vec3<float> tmp = headPosition + direction * yt;
  494. if (yt <= targetDistanceLimit && tmp.x >= (float)px
  495. && tmp.x < (float)px + 1.f && tmp.z >= (float)pz
  496. && tmp.z < (float)pz + 1.f)
  497. {
  498. dir = NORTH;
  499. py++;
  500. continue;
  501. }
  502. }
  503. if (direction.y < 0)
  504. {
  505. float yt = ((float)py - headPosition.y) / direction.y;
  506. Framework::Vec3<float> tmp = headPosition + direction * yt;
  507. if (yt <= targetDistanceLimit && tmp.x >= (float)px
  508. && tmp.x < (float)px + 1.f && tmp.z >= (float)pz
  509. && tmp.z < (float)pz + 1.f)
  510. {
  511. dir = SOUTH;
  512. py--;
  513. continue;
  514. }
  515. }
  516. if (direction.z > 0)
  517. {
  518. float zt = ((float)pz + 1.f - headPosition.z) / direction.z;
  519. Framework::Vec3<float> tmp = headPosition + direction * zt;
  520. if (zt <= targetDistanceLimit && tmp.x >= (float)px
  521. && tmp.x < (float)px + 1.f && tmp.y >= (float)py
  522. && tmp.y < (float)py + 1.f)
  523. {
  524. dir = BOTTOM;
  525. pz++;
  526. continue;
  527. }
  528. }
  529. if (direction.z < 0)
  530. {
  531. float zt = ((float)pz - headPosition.z) / direction.z;
  532. Framework::Vec3<float> tmp = headPosition + direction * zt;
  533. if (zt <= targetDistanceLimit && tmp.x >= (float)px
  534. && tmp.x < (float)px + 1.f && tmp.y >= (float)py
  535. && tmp.y < (float)py + 1)
  536. {
  537. dir = TOP;
  538. pz--;
  539. continue;
  540. }
  541. }
  542. if (target)
  543. {
  544. changed = true;
  545. }
  546. break;
  547. }
  548. float distSq = Framework::Vec3<float>((float)px, (float)py, (float)pz)
  549. .distanceSq(headPosition);
  550. Entity* zte = Game::INSTANCE->zDimension(dimensionId)
  551. ->zTarget(headPosition, direction, distSq);
  552. if (zte)
  553. {
  554. if (!target || !target->isEntity(zte->getId()))
  555. {
  556. cs.lock();
  557. delete target;
  558. target = new ActionTarget(zte->getId());
  559. cs.unlock();
  560. onTargetChange();
  561. }
  562. }
  563. else if (changed)
  564. {
  565. if (target && !found)
  566. {
  567. cs.lock();
  568. delete target;
  569. target = 0;
  570. cs.unlock();
  571. onTargetChange();
  572. }
  573. else
  574. {
  575. cs.lock();
  576. delete target;
  577. target = new ActionTarget({px, py, pz}, dir);
  578. cs.unlock();
  579. onTargetChange();
  580. }
  581. }
  582. }
  583. void Entity::notifyStatusBarObservers(NetworkMessage* msg)
  584. {
  585. statusBarObservable.notifyObservers(msg);
  586. }
  587. ItemSkill* Entity::zSkill(int itemType)
  588. {
  589. for (ItemSkill* skill : skills)
  590. {
  591. if (skill->getItemTypeId() == itemType)
  592. {
  593. return skill;
  594. }
  595. }
  596. return 0;
  597. }
  598. void Entity::calcBlockCollision(int& x, int& y, int& xl, int& yl)
  599. {
  600. Framework::Vec3<float> minXY = -boundingBox;
  601. Framework::Vec3<float> maxXY = boundingBox;
  602. Framework::Vec3<float> minXmaxY(minXY.x, maxXY.y, minXY.z);
  603. Framework::Vec3<float> maxXminY(maxXY.x, minXY.y, minXY.z);
  604. maxXY.z = minXY.z;
  605. minXY.rotateZ(rotation);
  606. maxXY.rotateZ(rotation);
  607. minXmaxY.rotateZ(rotation);
  608. maxXminY.rotateZ(rotation);
  609. minXY += location;
  610. maxXY += location;
  611. minXmaxY += location;
  612. maxXminY += location;
  613. Framework::Vec3<int> minXYI(
  614. (int)floor(minXY.x), (int)floor(minXY.y), (int)floor(minXY.z));
  615. Framework::Vec3<int> maxXYI(
  616. (int)floor(maxXY.x), (int)floor(maxXY.y), (int)floor(maxXY.z));
  617. Framework::Vec3<int> minXmaxYI(
  618. (int)floor(minXmaxY.x), (int)floor(minXmaxY.y), (int)floor(minXmaxY.z));
  619. Framework::Vec3<int> maxXminYI(
  620. (int)floor(maxXminY.x), (int)floor(maxXminY.y), (int)floor(maxXminY.z));
  621. x = minXYI.x;
  622. y = minXYI.y;
  623. if (x > minXmaxYI.x) x = minXmaxYI.x;
  624. if (x > maxXminYI.x) x = maxXminYI.x;
  625. if (x > maxXYI.x) x = maxXYI.x;
  626. if (y > minXmaxYI.y) y = minXmaxYI.y;
  627. if (y > maxXminYI.y) y = maxXminYI.y;
  628. if (y > maxXYI.y) y = maxXYI.y;
  629. xl = minXYI.x;
  630. if (xl < minXmaxYI.x) xl = minXmaxYI.x;
  631. if (xl < maxXminYI.x) xl = maxXminYI.x;
  632. if (xl < maxXYI.x) xl = maxXYI.x;
  633. yl = minXYI.y;
  634. if (yl < minXmaxYI.y) yl = minXmaxYI.y;
  635. if (yl < maxXminYI.y) yl = maxXminYI.y;
  636. if (yl < maxXYI.y) yl = maxXYI.y;
  637. xl = xl - x + 1;
  638. yl = yl - y + 1;
  639. if (collisionMapLength < xl * yl)
  640. {
  641. delete[] collisionMap;
  642. collisionMap = new bool[xl * yl];
  643. collisionMapLength = xl * yl;
  644. }
  645. memset(collisionMap, 0, xl * yl * sizeof(bool));
  646. int xi = minXYI.x - x;
  647. int yi = minXYI.y - y;
  648. collisionMap[xi + yi * xl] = 1;
  649. xi = maxXYI.x - x;
  650. yi = maxXYI.y - y;
  651. collisionMap[xi + yi * xl] = 1;
  652. xi = minXmaxYI.x - x;
  653. yi = minXmaxYI.y - y;
  654. collisionMap[xi + yi * xl] = 1;
  655. xi = maxXminYI.x - x;
  656. yi = maxXminYI.y - y;
  657. collisionMap[xi + yi * xl] = 1;
  658. auto dir = minXmaxY - minXY;
  659. float m = 0;
  660. if (abs(dir.x) >= abs(dir.y))
  661. {
  662. if (dir.x != 0 && dir.y != 0)
  663. {
  664. m = dir.y / dir.x;
  665. }
  666. float yy = minXY.y;
  667. for (int xx = (int)floor(minXY.x); xx < (int)floor(minXmaxY.x); xx++)
  668. {
  669. int xi = xx - x;
  670. int yi = (int)floor(yy) - y;
  671. if (xi >= xl || yi >= yl)
  672. {
  673. continue;
  674. }
  675. collisionMap[xi + yi * xl] = 1;
  676. yy += m;
  677. }
  678. }
  679. else
  680. {
  681. if (dir.x != 0 && dir.y != 0)
  682. {
  683. m = dir.x / dir.y;
  684. }
  685. float xx = minXY.x;
  686. for (int yy = (int)floor(minXY.y); yy < (int)floor(minXmaxY.y); yy++)
  687. {
  688. int xi = (int)floor(xx) - x;
  689. int yi = yy - y;
  690. if (xi >= xl || yi >= yl)
  691. {
  692. continue;
  693. }
  694. collisionMap[xi + yi * xl] = 1;
  695. xx += m;
  696. }
  697. }
  698. dir = maxXminY - minXY;
  699. m = 0;
  700. if (abs(dir.x) >= abs(dir.y))
  701. {
  702. if (dir.x != 0 && dir.y != 0)
  703. {
  704. m = dir.y / dir.x;
  705. }
  706. float yy = minXY.y;
  707. for (int xx = (int)floor(minXY.x); xx < (int)floor(maxXminY.x); xx++)
  708. {
  709. int xi = xx - x;
  710. int yi = (int)floor(yy) - y;
  711. if (xi >= xl || yi >= yl)
  712. {
  713. continue;
  714. }
  715. collisionMap[xi + yi * xl] = 1;
  716. yy += m;
  717. }
  718. }
  719. else
  720. {
  721. if (dir.x != 0 && dir.y != 0)
  722. {
  723. m = dir.x / dir.y;
  724. }
  725. float xx = minXY.x;
  726. for (int yy = (int)floor(minXY.y); yy < (int)floor(maxXminY.y); yy++)
  727. {
  728. int xi = (int)floor(xx) - x;
  729. int yi = yy - y;
  730. if (xi >= xl || yi >= yl)
  731. {
  732. continue;
  733. }
  734. collisionMap[xi + yi * xl] = 1;
  735. xx += m;
  736. }
  737. }
  738. dir = maxXY - maxXminY;
  739. m = 0;
  740. if (abs(dir.x) >= abs(dir.y))
  741. {
  742. if (dir.x != 0 && dir.y != 0)
  743. {
  744. m = dir.y / dir.x;
  745. }
  746. float yy = maxXminY.y;
  747. for (int xx = (int)floor(maxXminY.x); xx < (int)floor(maxXY.x); xx++)
  748. {
  749. int xi = xx - x;
  750. int yi = (int)floor(yy) - y;
  751. if (xi >= xl || yi >= yl)
  752. {
  753. continue;
  754. }
  755. collisionMap[xi + yi * xl] = 1;
  756. yy += m;
  757. }
  758. }
  759. else
  760. {
  761. if (dir.x != 0 && dir.y != 0)
  762. {
  763. m = dir.x / dir.y;
  764. }
  765. float xx = maxXminY.x;
  766. for (int yy = (int)floor(maxXminY.y); yy < (int)floor(maxXY.y); yy++)
  767. {
  768. int xi = (int)floor(xx) - x;
  769. int yi = yy - y;
  770. if (xi >= xl || yi >= yl)
  771. {
  772. continue;
  773. }
  774. collisionMap[xi + yi * xl] = 1;
  775. xx += m;
  776. }
  777. }
  778. dir = maxXY - minXmaxY;
  779. m = 0;
  780. if (abs(dir.x) >= abs(dir.y))
  781. {
  782. if (dir.x != 0 && dir.y != 0)
  783. {
  784. m = dir.y / dir.x;
  785. }
  786. float yy = minXmaxY.y;
  787. for (int xx = (int)floor(minXmaxY.x); xx < (int)floor(maxXY.x); xx++)
  788. {
  789. int xi = xx - x;
  790. int yi = (int)floor(yy) - y;
  791. if (xi >= xl || yi >= yl)
  792. {
  793. continue;
  794. }
  795. collisionMap[xi + yi * xl] = 1;
  796. yy += m;
  797. }
  798. }
  799. else
  800. {
  801. if (dir.x != 0 && dir.y != 0)
  802. {
  803. m = dir.x / dir.y;
  804. }
  805. float xx = minXmaxY.x;
  806. for (int yy = (int)floor(minXmaxY.y); yy < (int)floor(maxXY.y); yy++)
  807. {
  808. int xi = (int)floor(xx) - x;
  809. int yi = yy - y;
  810. if (xi >= xl || yi >= yl)
  811. {
  812. continue;
  813. }
  814. collisionMap[xi + yi * xl] = 1;
  815. xx += m;
  816. }
  817. }
  818. for (int yy = 0; yy < yl; yy++)
  819. {
  820. int min = xl;
  821. int max = -1;
  822. for (int xx = 0; xx < xl; xx++)
  823. {
  824. if (collisionMap[xx + yy * xl])
  825. {
  826. if (xx < min) min = xx;
  827. if (xx > max) max = xx;
  828. }
  829. }
  830. for (int xx = min; xx <= max; xx++)
  831. {
  832. collisionMap[xx + yy * xl] = 1;
  833. }
  834. }
  835. }
  836. bool Entity::isCollidingWithBlock(const Dimension* zDimension)
  837. {
  838. int x, y, xl, yl;
  839. calcBlockCollision(x, y, xl, yl);
  840. bool result = isCollidingWithBlock(zDimension, x, y, xl, yl);
  841. return result;
  842. }
  843. bool Entity::isCollidingWithBlock(
  844. const Dimension* zDimension, int x, int y, int xl, int yl)
  845. {
  846. for (int yy = 0; yy < yl; yy++)
  847. {
  848. for (int xx = 0; xx < xl; xx++)
  849. {
  850. if (collisionMap[xx + yy * xl])
  851. {
  852. for (int zz = (int)(location.z - boundingBox.z);
  853. zz <= (int)(location.z + boundingBox.z);
  854. zz++)
  855. {
  856. const Block* block = zDimension->zBlockOrDefault(
  857. Framework::Vec3<int>(x + xx, y + yy, zz));
  858. if (!block->isPassable())
  859. {
  860. return true;
  861. }
  862. }
  863. }
  864. }
  865. }
  866. return false;
  867. }
  868. void Entity::prepareTick(const Dimension* zDimension, double seconds) {}
  869. void Entity::tick(const Dimension* zDimension, double seconds)
  870. {
  871. if (removed) return;
  872. if (placeBlockCooldown > 0)
  873. {
  874. placeBlockCooldown -= seconds;
  875. }
  876. bool changed = 0;
  877. float rotSpeed = 0.f;
  878. if (movementFlags & MovementFlags::ROTATE_LEFT)
  879. {
  880. rotSpeed += 3.f * (float)seconds;
  881. }
  882. if (movementFlags & MovementFlags::ROTATE_RIGHT)
  883. {
  884. rotSpeed -= 3.f * (float)seconds;
  885. }
  886. if (movementFlags & MovementFlags::ROTATE_TO_FACE)
  887. {
  888. float rot = Framework::Vec2<float>(0, -1).angle({faceDir.x, faceDir.y});
  889. rotSpeed = rot - rotation;
  890. while (rotSpeed >= 2.f * (float)PI)
  891. {
  892. rotSpeed -= 2.f * (float)PI;
  893. }
  894. while (rotSpeed <= -2.f * (float)PI)
  895. {
  896. rotSpeed += 2.f * (float)PI;
  897. }
  898. }
  899. if (rotSpeed != 0.f)
  900. {
  901. float last = rotation;
  902. rotation += rotSpeed;
  903. while (rotation >= 2.f * (float)PI)
  904. {
  905. rotation -= 2.f * (float)PI;
  906. }
  907. while (rotation <= -2.f * (float)PI)
  908. {
  909. rotation += 2.f * (float)PI;
  910. }
  911. if (last != rotation)
  912. {
  913. if (isCollidingWithBlock(zDimension))
  914. {
  915. rotation -= rotSpeed;
  916. }
  917. else
  918. {
  919. changed = 1;
  920. }
  921. }
  922. }
  923. Framework::Vec3<float> moveDir(0.f, 0.f, 0.f);
  924. if (movementFlags & MovementFlags::WALK_FORWARD)
  925. {
  926. moveDir.x += cosf(rotation - (float)PI / 2.f);
  927. moveDir.y += sinf(rotation - (float)PI / 2.f);
  928. }
  929. if (movementFlags & MovementFlags::WALK_BACKWARD)
  930. {
  931. moveDir.x -= cosf(rotation - (float)PI / 2.f);
  932. moveDir.y -= sinf(rotation - (float)PI / 2.f);
  933. }
  934. if (movementFlags & MovementFlags::WALK_LEFT)
  935. {
  936. moveDir.x += cosf(rotation + (float)PI);
  937. moveDir.y += sinf(rotation + (float)PI);
  938. }
  939. if (movementFlags & MovementFlags::WALK_RIGHT)
  940. {
  941. moveDir.x += cosf(rotation);
  942. moveDir.y += sinf(rotation);
  943. }
  944. if (movementFlags & MovementFlags::FLYING
  945. && movementFlags & MovementFlags::JUMPING)
  946. {
  947. moveDir.z += 1.f;
  948. movementFlags &= ~MovementFlags::GROUND_CONTACT;
  949. }
  950. if (movementFlags & MovementFlags::FLYING
  951. && movementFlags & MovementFlags::SNEAKING)
  952. {
  953. moveDir.z -= 1.f;
  954. }
  955. float staminaCost = 0.f;
  956. if (moveDir.x != 0.f || moveDir.y != 0.f)
  957. {
  958. moveDir.normalize();
  959. moveDir *= maxMovementSpeed * (float)seconds;
  960. if (movementFlags & MovementFlags::SPRINTING)
  961. {
  962. moveDir *= 2.f;
  963. }
  964. if (movementFlags & MovementFlags::SNEAKING
  965. && !(movementFlags & MovementFlags::FLYING))
  966. {
  967. moveDir *= 0.5f;
  968. }
  969. staminaCost = moveDir.getLength() / (maxMovementSpeed * 10);
  970. if (stamina < staminaCost)
  971. {
  972. staminaCost = stamina;
  973. moveDir *= stamina / staminaCost;
  974. }
  975. }
  976. if (!(movementFlags & MovementFlags::FLYING)
  977. && movementFlags & MovementFlags::JUMPING
  978. && movementFlags & MovementFlags::GROUND_CONTACT)
  979. {
  980. if (stamina > staminaCost + 0.02f)
  981. {
  982. staminaCost += 0.02f;
  983. speed.z += jumpSpeed;
  984. movementFlags &= ~MovementFlags::GROUND_CONTACT;
  985. }
  986. }
  987. if ((!(movementFlags & MovementFlags::FLYING)
  988. && (speed.x != 0.f || speed.y != 0.f || speed.z != 0.f
  989. || moveDir.x != 0.f || moveDir.y != 0.f || moveDir.z != 0.f
  990. || !(movementFlags & MovementFlags::GROUND_CONTACT))))
  991. {
  992. speed.z
  993. -= zDimension->getGravity() * gravityMultiplier * (float)seconds;
  994. }
  995. moveDir += speed * (float)seconds;
  996. bool staminaChanged = staminaCost != 0.f;
  997. stamina -= staminaCost;
  998. if (stamina <= maxStamina - (float)seconds)
  999. {
  1000. if (getThirst() > 0 && getHunger() > 0)
  1001. { // TODO: modify regen rate based on hunger/thirst
  1002. stamina += (float)seconds;
  1003. staminaChanged = 1;
  1004. setHunger(hunger - (float)seconds / 5.f);
  1005. setThirst(thirst - (float)seconds / 2.5f);
  1006. }
  1007. }
  1008. if (staminaChanged)
  1009. {
  1010. setStamina(stamina); // notify observers
  1011. }
  1012. if (moveDir.x != 0.f || moveDir.y != 0.f || moveDir.z != 0.f)
  1013. {
  1014. bool collided = isCollidingWithBlock(zDimension);
  1015. while (abs(moveDir.x) > 1.f)
  1016. {
  1017. if (moveDir.x > 0.f)
  1018. {
  1019. location.x += 1.f;
  1020. if (!collided && isCollidingWithBlock(zDimension))
  1021. {
  1022. moveDir.x = 0.f;
  1023. speed.x = 0.f;
  1024. location.x -= 1.f;
  1025. }
  1026. else
  1027. {
  1028. moveDir.x -= 1.f;
  1029. changed = 1;
  1030. }
  1031. }
  1032. else
  1033. {
  1034. location.x -= 1.f;
  1035. if (!collided && isCollidingWithBlock(zDimension))
  1036. {
  1037. moveDir.x = 0.f;
  1038. speed.x = 0.f;
  1039. location.x += 1.f;
  1040. }
  1041. else
  1042. {
  1043. moveDir.x += 1.f;
  1044. changed = 1;
  1045. }
  1046. }
  1047. }
  1048. if (moveDir.x != 0.f)
  1049. {
  1050. location.x += moveDir.x;
  1051. if (!collided && isCollidingWithBlock(zDimension))
  1052. {
  1053. location.x -= moveDir.x;
  1054. speed.x = 0.f;
  1055. }
  1056. else
  1057. {
  1058. changed = 1;
  1059. }
  1060. }
  1061. while (abs(moveDir.y) > 1.f)
  1062. {
  1063. if (moveDir.y > 0.f)
  1064. {
  1065. location.y += 1.f;
  1066. if (!collided && isCollidingWithBlock(zDimension))
  1067. {
  1068. moveDir.y = 0.f;
  1069. location.y -= 1.f;
  1070. speed.y = 0.f;
  1071. }
  1072. else
  1073. {
  1074. moveDir.y -= 1.f;
  1075. changed = 1;
  1076. }
  1077. }
  1078. else
  1079. {
  1080. location.y -= 1.f;
  1081. if (!collided && isCollidingWithBlock(zDimension))
  1082. {
  1083. moveDir.y = 0.f;
  1084. location.y += 1.f;
  1085. speed.y = 0.f;
  1086. }
  1087. else
  1088. {
  1089. moveDir.y += 1.f;
  1090. changed = 1;
  1091. }
  1092. }
  1093. }
  1094. if (moveDir.y != 0.f)
  1095. {
  1096. location.y += moveDir.y;
  1097. if (!collided && isCollidingWithBlock(zDimension))
  1098. {
  1099. location.y -= moveDir.y;
  1100. speed.y = 0.f;
  1101. }
  1102. else
  1103. {
  1104. changed = 1;
  1105. }
  1106. }
  1107. while (abs(moveDir.z) > 1.f)
  1108. {
  1109. if (moveDir.z > 0.f)
  1110. {
  1111. location.z += 1.f;
  1112. if (isCollidingWithBlock(zDimension))
  1113. {
  1114. moveDir.z = 0.f;
  1115. location.z -= 1.f;
  1116. speed.z = 0.f;
  1117. }
  1118. else
  1119. {
  1120. moveDir.z -= 1.f;
  1121. changed = 1;
  1122. }
  1123. }
  1124. else
  1125. {
  1126. location.z -= 1.f;
  1127. if (isCollidingWithBlock(zDimension))
  1128. {
  1129. moveDir.z = 0.f;
  1130. location.z += 1.f;
  1131. onFall(speed.z);
  1132. speed.z = 0.f;
  1133. movementFlags |= MovementFlags::GROUND_CONTACT;
  1134. }
  1135. else
  1136. {
  1137. moveDir.z += 1.f;
  1138. changed = 1;
  1139. }
  1140. }
  1141. }
  1142. if (moveDir.z != 0.f)
  1143. {
  1144. location.z += moveDir.z;
  1145. if (isCollidingWithBlock(zDimension))
  1146. {
  1147. if (speed.z < 0.f)
  1148. {
  1149. onFall(speed.z);
  1150. speed.z = 0.f;
  1151. movementFlags |= MovementFlags::GROUND_CONTACT;
  1152. }
  1153. else
  1154. {
  1155. changed = 1;
  1156. }
  1157. location.z -= moveDir.z;
  1158. }
  1159. else
  1160. {
  1161. changed = 1;
  1162. }
  1163. }
  1164. }
  1165. if (movementFlags & MovementFlags::GROUND_CONTACT)
  1166. {
  1167. if (speed.x != 0)
  1168. {
  1169. if (speed.x > (float)seconds)
  1170. {
  1171. speed.x -= (float)seconds;
  1172. }
  1173. else if (speed.x < -(float)seconds)
  1174. {
  1175. speed.x += (float)seconds;
  1176. }
  1177. else
  1178. {
  1179. speed.x = 0;
  1180. }
  1181. }
  1182. if (speed.y != 0)
  1183. {
  1184. if (speed.y > (float)seconds)
  1185. {
  1186. speed.y -= (float)seconds;
  1187. }
  1188. else if (speed.y < -(float)seconds)
  1189. {
  1190. speed.y += (float)seconds;
  1191. }
  1192. else
  1193. {
  1194. speed.y = 0;
  1195. }
  1196. }
  1197. }
  1198. Framework::Point chunkCenter
  1199. = Game::INSTANCE->getChunkCenter((int)location.x, (int)location.y);
  1200. Chunk* zCurrentChunk = 0;
  1201. if (dimensionId != lastDimensionId || chunkCenter != lastChunkCenter)
  1202. {
  1203. Dimension* lastDimension = Game::INSTANCE->zDimension(lastDimensionId);
  1204. Dimension* currentDimension = Game::INSTANCE->zDimension(dimensionId);
  1205. zCurrentChunk
  1206. = currentDimension ? currentDimension->zChunk(chunkCenter) : 0;
  1207. Chunk* zLastChunk
  1208. = lastDimension ? lastDimension->zChunk(lastChunkCenter) : 0;
  1209. if (lastDimensionId != -1)
  1210. {
  1211. if (zLastChunk)
  1212. {
  1213. zLastChunk->onEntityLeaves(
  1214. this, lastDimensionId == dimensionId ? zCurrentChunk : 0);
  1215. }
  1216. }
  1217. if (zCurrentChunk)
  1218. {
  1219. zCurrentChunk->onEntityEnters(
  1220. this, lastDimensionId == dimensionId ? zLastChunk : 0);
  1221. }
  1222. lastDimensionId = dimensionId;
  1223. lastChunkCenter = chunkCenter;
  1224. }
  1225. if (changed)
  1226. {
  1227. if (!zCurrentChunk)
  1228. {
  1229. Dimension* currentDimension
  1230. = Game::INSTANCE->zDimension(dimensionId);
  1231. zCurrentChunk
  1232. = currentDimension ? currentDimension->zChunk(chunkCenter) : 0;
  1233. }
  1234. if (zCurrentChunk)
  1235. {
  1236. NetworkMessage* msg = new NetworkMessage();
  1237. msg->sendEntityMovement(this, (float)seconds);
  1238. zCurrentChunk->notifyObservers(msg);
  1239. }
  1240. }
  1241. }
  1242. void Entity::api(Framework::StreamReader* zRequest,
  1243. NetworkMessage* zResponse,
  1244. Entity* zSource)
  1245. {
  1246. char type;
  1247. zRequest->read(&type, 1);
  1248. switch (type)
  1249. {
  1250. case 0: // request status bar state
  1251. {
  1252. char len;
  1253. zRequest->read(&len, 1);
  1254. char* guiId = new char[(int)len + 1];
  1255. zRequest->read(guiId, len);
  1256. guiId[(int)len] = 0;
  1257. int processor;
  1258. zRequest->read((char*)&processor, 4);
  1259. zResponse->addressUIElement(guiId, processor);
  1260. statusBarObservable.addObserver(zSource, guiId, processor);
  1261. char* msg = new char[33];
  1262. msg[0] = 0;
  1263. *(float*)(msg + 1) = getMaxHP();
  1264. *(float*)(msg + 5) = getCurrentHP();
  1265. *(float*)(msg + 9) = getMaxStamina();
  1266. *(float*)(msg + 13) = getStamina();
  1267. *(float*)(msg + 17) = getMaxHunger();
  1268. *(float*)(msg + 21) = getHunger();
  1269. *(float*)(msg + 25) = getMaxThirst();
  1270. *(float*)(msg + 29) = getThirst();
  1271. zResponse->setMessage(msg, 33);
  1272. delete[] guiId;
  1273. break;
  1274. }
  1275. case 1: // remove status bar observer
  1276. {
  1277. char len;
  1278. zRequest->read(&len, 1);
  1279. char* guiId = new char[(int)len + 1];
  1280. zRequest->read(guiId, len);
  1281. guiId[(int)len] = 0;
  1282. int processor;
  1283. zRequest->read((char*)&processor, 4);
  1284. statusBarObservable.removeObserver(zSource, guiId, processor);
  1285. delete[] guiId;
  1286. break;
  1287. }
  1288. case 2: // TODO: component request
  1289. break;
  1290. }
  1291. }
  1292. void Entity::onFall(float collisionSpeed)
  1293. {
  1294. if (collisionSpeed > 20)
  1295. {
  1296. setHP(this, 0, 0, getCurrentHP() - (collisionSpeed - 20.f) / 2.5f);
  1297. }
  1298. }
  1299. Framework::XML::Element* Entity::getTargetUIML() const
  1300. {
  1301. return UIMLBuilder::createContainer()
  1302. ->addChild(UIMLBuilder::createTextAuto(
  1303. Game::INSTANCE->zEntityType(typeId)->getName())
  1304. ->setID("type")
  1305. ->build())
  1306. ->build();
  1307. }
  1308. void Entity::setChatSecurityLevel(int level)
  1309. {
  1310. chatSecurityLevel = level;
  1311. }
  1312. void Entity::setPosition(Framework::Vec3<float> pos)
  1313. {
  1314. location = pos;
  1315. }
  1316. void Entity::takeDamage(
  1317. Entity* zSource, Item* zUsedItem, ItemSkill* zUsedSkill, float damage)
  1318. {
  1319. currentHP -= damage;
  1320. if (currentHP <= 0)
  1321. {
  1322. currentHP = 0;
  1323. onDeath(zSource, zUsedItem, zUsedSkill);
  1324. }
  1325. }
  1326. void Entity::setHP(
  1327. Entity* zActor, Item* zUsedItem, ItemSkill* zUsedSkill, float hp)
  1328. {
  1329. currentHP = MIN(MAX(hp, 0), maxHP);
  1330. NetworkMessage* msg = new NetworkMessage();
  1331. char* message = new char[9];
  1332. message[0] = 1;
  1333. *(float*)(message + 1) = getMaxHP();
  1334. *(float*)(message + 5) = getCurrentHP();
  1335. msg->setMessage(message, 9);
  1336. notifyStatusBarObservers(msg);
  1337. if (currentHP == 0)
  1338. {
  1339. onDeath(zActor, zUsedItem, zUsedSkill);
  1340. }
  1341. }
  1342. void Entity::setStamina(float stamina)
  1343. {
  1344. this->stamina = MIN(MAX(stamina, 0), maxStamina);
  1345. NetworkMessage* msg = new NetworkMessage();
  1346. char* message = new char[9];
  1347. message[0] = 2;
  1348. *(float*)(message + 1) = getMaxStamina();
  1349. *(float*)(message + 5) = getStamina();
  1350. msg->setMessage(message, 9);
  1351. notifyStatusBarObservers(msg);
  1352. }
  1353. void Entity::setHunger(float hunger)
  1354. {
  1355. this->hunger = MIN(MAX(hunger, 0), maxHunger);
  1356. NetworkMessage* msg = new NetworkMessage();
  1357. char* message = new char[9];
  1358. message[0] = 3;
  1359. *(float*)(message + 1) = getMaxHunger();
  1360. *(float*)(message + 5) = getHunger();
  1361. msg->setMessage(message, 9);
  1362. notifyStatusBarObservers(msg);
  1363. }
  1364. void Entity::setThirst(float thirst)
  1365. {
  1366. this->thirst = MIN(MAX(thirst, 0), maxThirst);
  1367. NetworkMessage* msg = new NetworkMessage();
  1368. char* message = new char[9];
  1369. message[0] = 4;
  1370. *(float*)(message + 1) = getMaxThirst();
  1371. *(float*)(message + 5) = getThirst();
  1372. msg->setMessage(message, 9);
  1373. notifyStatusBarObservers(msg);
  1374. }
  1375. void Entity::setGravityMultiplier(float multiplier)
  1376. {
  1377. gravityMultiplier = multiplier;
  1378. }
  1379. float Entity::getMaxHP() const
  1380. {
  1381. return maxHP;
  1382. }
  1383. float Entity::getCurrentHP() const
  1384. {
  1385. return currentHP;
  1386. }
  1387. float Entity::getStamina() const
  1388. {
  1389. return stamina;
  1390. }
  1391. float Entity::getMaxStamina() const
  1392. {
  1393. return maxStamina;
  1394. }
  1395. float Entity::getHunger() const
  1396. {
  1397. return hunger;
  1398. }
  1399. float Entity::getMaxHunger() const
  1400. {
  1401. return maxHunger;
  1402. }
  1403. float Entity::getThirst() const
  1404. {
  1405. return thirst;
  1406. }
  1407. float Entity::getMaxThirst() const
  1408. {
  1409. return maxThirst;
  1410. }
  1411. Framework::Vec3<float> Entity::getSpeed() const
  1412. {
  1413. return speed;
  1414. }
  1415. Framework::Vec3<float> Entity::getFaceDir() const
  1416. {
  1417. return faceDir;
  1418. }
  1419. Framework::Vec3<float> Entity::getPosition() const
  1420. {
  1421. return location;
  1422. }
  1423. float Entity::getGravityMultiplier() const
  1424. {
  1425. return gravityMultiplier;
  1426. }
  1427. float Entity::getJumpSpeed() const
  1428. {
  1429. return jumpSpeed;
  1430. }
  1431. void Entity::setJumpSpeed(float speed)
  1432. {
  1433. jumpSpeed = speed;
  1434. }
  1435. bool Entity::isRemoved() const
  1436. {
  1437. return removed;
  1438. }
  1439. const EntityType* Entity::zType() const
  1440. {
  1441. return Game::INSTANCE->zEntityType(typeId);
  1442. }
  1443. const ActionTarget* Entity::zTarget() const
  1444. {
  1445. return target;
  1446. }
  1447. int Entity::getId() const
  1448. {
  1449. return id;
  1450. }
  1451. bool Entity::hasDefaultModel() const
  1452. {
  1453. return 1;
  1454. }
  1455. ModelInfo* Entity::zSpecialModel() const
  1456. {
  1457. return 0;
  1458. }
  1459. float Entity::getMaxSpeed() const
  1460. {
  1461. return maxMovementSpeed;
  1462. }
  1463. bool Entity::isMoving() const
  1464. {
  1465. return movementFlags > 0;
  1466. }
  1467. int Entity::getChatSecurityLevel() const
  1468. {
  1469. return chatSecurityLevel;
  1470. }
  1471. Framework::Maybe<Framework::Point> Entity::getLastSavedChunkCenter() const
  1472. {
  1473. return lastSavedChunkCenter;
  1474. }
  1475. void Entity::setLastSavedChunkCenter(Framework::Point pos)
  1476. {
  1477. lastSavedChunkCenter = Framework::Maybe<Framework::Point>::of(pos);
  1478. }
  1479. void Entity::setLastChunk(int dimensionId, Framework::Point chankCenter)
  1480. {
  1481. lastDimensionId = dimensionId;
  1482. lastChunkCenter = chankCenter;
  1483. }
  1484. void Entity::setRemoved()
  1485. {
  1486. removed = true;
  1487. }
  1488. double Entity::getHitDistance(
  1489. Framework::Vec3<float> rayOrigin, Framework::Vec3<float> rayDirection) const
  1490. {
  1491. Framework::Vec3<float> rotatedRayOrigin
  1492. = Framework::Vec3<float>(rayOrigin).rotateZ(-rotation);
  1493. Framework::Vec3<float> rotatedRayDirection
  1494. = Framework::Vec3<float>(rayDirection).rotateZ(-rotation);
  1495. rotatedRayDirection.normalize();
  1496. if (rotatedRayDirection.x != 0)
  1497. {
  1498. float d = 0.f;
  1499. if (rotatedRayDirection.x > 0)
  1500. {
  1501. float border = getPosition().x - boundingBox.x;
  1502. d = (border - rotatedRayOrigin.x) / rotatedRayDirection.x;
  1503. }
  1504. else if (rotatedRayDirection.x < 0)
  1505. {
  1506. float border = getPosition().x + boundingBox.x;
  1507. d = (border - rotatedRayOrigin.x) / rotatedRayDirection.x;
  1508. }
  1509. if (d > 0)
  1510. {
  1511. Framework::Vec3<float> hitPoint
  1512. = rotatedRayOrigin + rotatedRayDirection * d;
  1513. if (hitPoint.y >= getPosition().y - boundingBox.y
  1514. && hitPoint.y <= getPosition().y + boundingBox.y
  1515. && hitPoint.z >= getPosition().z - boundingBox.z
  1516. && hitPoint.z <= getPosition().z + boundingBox.z)
  1517. {
  1518. return d;
  1519. }
  1520. }
  1521. }
  1522. if (rotatedRayDirection.y != 0)
  1523. {
  1524. float d = 0.f;
  1525. if (rotatedRayDirection.y > 0)
  1526. {
  1527. float border = getPosition().y - boundingBox.y;
  1528. d = (border - rotatedRayOrigin.y) / rotatedRayDirection.y;
  1529. }
  1530. else if (rotatedRayDirection.y < 0)
  1531. {
  1532. float border = getPosition().y + boundingBox.y;
  1533. d = (border - rotatedRayOrigin.y) / rotatedRayDirection.y;
  1534. }
  1535. if (d > 0)
  1536. {
  1537. Framework::Vec3<float> hitPoint
  1538. = rotatedRayOrigin + rotatedRayDirection * d;
  1539. if (hitPoint.x >= getPosition().x - boundingBox.x
  1540. && hitPoint.x <= getPosition().x + boundingBox.x
  1541. && hitPoint.z >= getPosition().z - boundingBox.z
  1542. && hitPoint.z <= getPosition().z + boundingBox.z)
  1543. {
  1544. return d;
  1545. }
  1546. }
  1547. }
  1548. if (rotatedRayDirection.z != 0)
  1549. {
  1550. float d = 0.f;
  1551. if (rotatedRayDirection.z > 0)
  1552. {
  1553. float border = getPosition().z - boundingBox.z;
  1554. d = (border - rotatedRayOrigin.z) / rotatedRayDirection.z;
  1555. }
  1556. else if (rotatedRayDirection.z < 0)
  1557. {
  1558. float border = getPosition().z + boundingBox.z;
  1559. d = (border - rotatedRayOrigin.z) / rotatedRayDirection.z;
  1560. }
  1561. if (d > 0)
  1562. {
  1563. Framework::Vec3<float> hitPoint
  1564. = rotatedRayOrigin + rotatedRayDirection * d;
  1565. if (hitPoint.x >= getPosition().x - boundingBox.x
  1566. && hitPoint.x <= getPosition().x + boundingBox.x
  1567. && hitPoint.y >= getPosition().y - boundingBox.y
  1568. && hitPoint.y <= getPosition().y + boundingBox.y)
  1569. {
  1570. return d;
  1571. }
  1572. }
  1573. }
  1574. return NAN;
  1575. }
  1576. float Entity::getRotation() const
  1577. {
  1578. return rotation;
  1579. }