Entity.cpp 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079
  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. ActionTarget::ActionTarget(Framework::Vec3<int> blockPos, Direction blockSide)
  12. : blockPos(blockPos),
  13. targetBlockSide(blockSide),
  14. entityId(-1)
  15. {}
  16. ActionTarget::ActionTarget(int entityId)
  17. : entityId(entityId)
  18. {}
  19. bool ActionTarget::isBlock(
  20. Framework::Vec3<int> blockPos, Direction blockSide) const
  21. {
  22. return this->entityId == -1 && this->blockPos == blockPos
  23. && (this->targetBlockSide == targetBlockSide
  24. || blockSide == NO_DIRECTION);
  25. }
  26. bool ActionTarget::isEntity(int entityId) const
  27. {
  28. return this->entityId == entityId;
  29. }
  30. bool ActionTarget::useItemSkillOnTarget(
  31. Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem)
  32. {
  33. if (entityId >= 0)
  34. {
  35. Entity* target = Game::INSTANCE->zEntity(entityId);
  36. if (target)
  37. {
  38. return zItemSkill->use(zActor, zUsedItem, target);
  39. }
  40. }
  41. else
  42. {
  43. Block* block = Game::INSTANCE->zRealBlockInstance(
  44. blockPos, zActor->getDimensionId());
  45. if (block)
  46. {
  47. return zItemSkill->use(zActor, zUsedItem, block);
  48. }
  49. }
  50. return 0;
  51. }
  52. bool ActionTarget::interactItemSkillOnTarget(
  53. Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem)
  54. {
  55. if (zItemSkill)
  56. {
  57. if (entityId >= 0)
  58. {
  59. Entity* target = Game::INSTANCE->zEntity(entityId);
  60. if (target) return zItemSkill->interact(zActor, zUsedItem, target);
  61. }
  62. else
  63. {
  64. Block* block = Game::INSTANCE->zRealBlockInstance(
  65. blockPos, zActor->getDimensionId());
  66. if (block) return zItemSkill->interact(zActor, zUsedItem, block);
  67. }
  68. }
  69. else
  70. {
  71. bool itemChanged = 0;
  72. if (entityId >= 0)
  73. {
  74. Block* block = Game::INSTANCE->zRealBlockInstance(
  75. blockPos, zActor->getDimensionId());
  76. if (block) block->interact(zUsedItem, zActor, itemChanged);
  77. }
  78. else
  79. {
  80. Block* block = Game::INSTANCE->zRealBlockInstance(
  81. blockPos, zActor->getDimensionId());
  82. if (block) block->interact(zUsedItem, zActor, itemChanged);
  83. }
  84. return itemChanged;
  85. }
  86. return 0;
  87. }
  88. bool ActionTarget::placeBlock(Entity* zActor, Item* zItem)
  89. {
  90. if (zActor->getStamina() > 0.2f)
  91. {
  92. if (zItem->canBePlacedAt(zActor->getDimensionId(),
  93. blockPos + getDirection(targetBlockSide)))
  94. {
  95. Block* block = zItem->zPlacedBlockType()->createBlockAt(
  96. blockPos + getDirection(targetBlockSide),
  97. zActor->getDimensionId(),
  98. zItem);
  99. if (block)
  100. {
  101. Game::INSTANCE->zDimension(zActor->getDimensionId())
  102. ->placeBlock(block->getPos(), block);
  103. zItem->onPlaced();
  104. zActor->setStamina(zActor->getStamina() - 0.2f);
  105. return 1;
  106. }
  107. }
  108. }
  109. return 0;
  110. }
  111. void ActionTarget::toMessage(
  112. const ActionTarget* zTarget, int dimensionId, NetworkMessage* zMsg)
  113. {
  114. if (zTarget)
  115. {
  116. if (zTarget->entityId >= 0)
  117. {
  118. Entity* zEntity = Game::INSTANCE->zEntity(zTarget->entityId);
  119. if (zEntity)
  120. {
  121. Framework::XML::Element* targetUIML = zEntity->getTargetUIML();
  122. Framework::Text targetUIMLText
  123. = targetUIML ? targetUIML->toString() : Framework::Text();
  124. targetUIML->release();
  125. char* message = new char[8 + targetUIMLText.getLength()];
  126. message[0] = 3;
  127. message[1] = 1;
  128. *(int*)(message + 2) = zTarget->entityId;
  129. *(short*)(message + 6) = (short)targetUIMLText.getLength();
  130. memcpy(message + 8,
  131. targetUIMLText.getText(),
  132. targetUIMLText.getLength());
  133. zMsg->setMessage(message, 8 + targetUIMLText.getLength());
  134. }
  135. else
  136. {
  137. char* message = new char[2];
  138. message[0] = 3;
  139. message[1] = 0;
  140. zMsg->setMessage(message, 2);
  141. }
  142. }
  143. else
  144. {
  145. Framework::XML::Element* targetUIML = 0;
  146. auto block
  147. = Game::INSTANCE->zBlockAt(zTarget->blockPos, dimensionId, 0);
  148. if (block.isA())
  149. {
  150. targetUIML = block.getA()->getTargetUIML();
  151. }
  152. else if (block.isB())
  153. {
  154. targetUIML
  155. = Game::INSTANCE->zBlockType(block.getB())->getTargetUIML();
  156. }
  157. Framework::Text targetUIMLText
  158. = targetUIML ? targetUIML->toString() : Framework::Text();
  159. char* message = new char[18 + targetUIMLText.getLength() + 2];
  160. message[0] = 3;
  161. message[1] = 2;
  162. *(int*)(message + 2) = zTarget->blockPos.x;
  163. *(int*)(message + 6) = zTarget->blockPos.y;
  164. *(int*)(message + 10) = zTarget->blockPos.z;
  165. *(int*)(message + 14) = zTarget->targetBlockSide;
  166. short len = (short)targetUIMLText.getLength();
  167. *(short*)(message + 18) = len;
  168. memcpy(message + 20, targetUIMLText.getText(), len);
  169. zMsg->setMessage(message, 18 + len + 2);
  170. }
  171. }
  172. else
  173. {
  174. char* message = new char[2];
  175. message[0] = 3;
  176. message[1] = 0;
  177. zMsg->setMessage(message, 2);
  178. }
  179. }
  180. void ActionTarget::save(ActionTarget* zTarget, Framework::StreamWriter* zWriter)
  181. {
  182. if (zTarget)
  183. {
  184. if (zTarget->entityId >= 0)
  185. {
  186. char b = 1;
  187. zWriter->schreibe(&b, 1);
  188. zWriter->schreibe((char*)&zTarget->entityId, 4);
  189. }
  190. else
  191. {
  192. char b = 2;
  193. zWriter->schreibe(&b, 1);
  194. zWriter->schreibe((char*)&zTarget->blockPos.x, 4);
  195. zWriter->schreibe((char*)&zTarget->blockPos.y, 4);
  196. zWriter->schreibe((char*)&zTarget->blockPos.z, 4);
  197. zWriter->schreibe((char*)&zTarget->targetBlockSide, 4);
  198. }
  199. }
  200. else
  201. {
  202. char b = 0;
  203. zWriter->schreibe(&b, 1);
  204. }
  205. }
  206. ActionTarget* ActionTarget::load(Framework::StreamReader* zReader)
  207. {
  208. char b;
  209. zReader->lese(&b, 1);
  210. if (b == 1)
  211. {
  212. int id;
  213. zReader->lese((char*)&id, 4);
  214. return new ActionTarget(id);
  215. }
  216. else if (b == 2)
  217. {
  218. Framework::Vec3<int> pos;
  219. Direction side;
  220. zReader->lese((char*)&pos.x, 4);
  221. zReader->lese((char*)&pos.y, 4);
  222. zReader->lese((char*)&pos.z, 4);
  223. zReader->lese((char*)&side, 4);
  224. return new ActionTarget(pos, side);
  225. }
  226. return 0;
  227. }
  228. Entity::Entity(
  229. int typeId, Framework::Vec3<float> location, int dimensionId, int entityId)
  230. : Inventory(location, dimensionId, true),
  231. chatSecurityLevel(0),
  232. lastChunkCenter(0, 0),
  233. lastSavedChunkCenter(Framework::Maybe<Framework::Punkt>::empty()),
  234. lastDimensionId(-1),
  235. speed(0, 0, 0),
  236. faceDir(1, 0, 0),
  237. target(0),
  238. typeId(typeId),
  239. removed(0),
  240. gravityMultiplier(1.f),
  241. jumpSpeed(0.f),
  242. id(entityId),
  243. placeBlockCooldown(0)
  244. {}
  245. void Entity::onDeath(Entity* zActor, Item* zUsedItem, ItemSkill* zUsedSkill)
  246. {
  247. if (!removed)
  248. {
  249. for (DropConfig* config : zType()->getDropConfigs())
  250. {
  251. config->onObjectDestroyed(zActor, zUsedItem, zUsedSkill, this);
  252. }
  253. Dimension* dim = Game::INSTANCE->zDimension(dimensionId);
  254. if (dim)
  255. {
  256. Chunk* chunk = dim->zChunk(lastChunkCenter);
  257. if (chunk)
  258. {
  259. chunk->onEntityLeaves(this, 0);
  260. }
  261. dim->removeEntity(id);
  262. }
  263. removed = 1;
  264. }
  265. }
  266. bool Entity::useItem(int typeId, ItemStack* zStack, bool left)
  267. {
  268. if (left)
  269. {
  270. if (!zStack || !zStack->zItem() || zStack->zItem()->isUsable())
  271. {
  272. cs.lock();
  273. if (target)
  274. {
  275. ItemSkill* selected = zSkill(typeId);
  276. if (!selected)
  277. {
  278. selected = Game::INSTANCE->zItemType(typeId)
  279. ->createDefaultItemSkill();
  280. selected->setItemTypeId(typeId);
  281. if (selected) skills.add(selected);
  282. }
  283. if (!selected)
  284. {
  285. selected = zSkill(ItemTypeEnum::PLAYER_HAND);
  286. selected->setItemTypeId(ItemTypeEnum::PLAYER_HAND);
  287. }
  288. bool result = target->useItemSkillOnTarget(this,
  289. selected,
  290. !zStack || zStack->getSize() > 1 ? 0
  291. : (Item*)zStack->zItem());
  292. cs.unlock();
  293. return result;
  294. }
  295. cs.unlock();
  296. }
  297. else
  298. {
  299. useItem(ItemTypeEnum::PLAYER_HAND, 0, left);
  300. }
  301. }
  302. else
  303. {
  304. if (zStack && zStack->zItem() && zStack->zItem()->isPlaceable()
  305. && zStack->getSize() > 0)
  306. { // place item
  307. cs.lock();
  308. if (target)
  309. {
  310. if (placeBlockCooldown <= 0)
  311. {
  312. Item* item = zStack->extractFromStack();
  313. bool result = target->placeBlock(this, item);
  314. if (item->getHp() > 0)
  315. {
  316. if (!zStack->addToStack(
  317. dynamic_cast<Item*>(item->getThis())))
  318. {
  319. ItemStack* newStack = new ItemStack(item, 1);
  320. addItems(newStack, NO_DIRECTION, 0);
  321. if (newStack->getSize())
  322. {
  323. Game::INSTANCE->spawnItem(
  324. location, dimensionId, newStack);
  325. }
  326. }
  327. else
  328. {
  329. item->release();
  330. }
  331. }
  332. else
  333. {
  334. item->release();
  335. }
  336. if (result)
  337. {
  338. placeBlockCooldown = 15;
  339. }
  340. cs.unlock();
  341. return result;
  342. }
  343. else
  344. {
  345. cs.unlock();
  346. return 0;
  347. }
  348. }
  349. cs.unlock();
  350. }
  351. if (zStack && zStack->zItem() && zStack->zItem()->isEatable()
  352. && zStack->getSize() > 0)
  353. { // eat item
  354. if (zStack->getSize() == 1)
  355. {
  356. return ((Item*)zStack->zItem())->applyFoodEffects(this);
  357. }
  358. else
  359. {
  360. if (zStack->zItem()->canApplyFoodEffectsFully(this))
  361. {
  362. Item* item = zStack->extractFromStack();
  363. item->applyFoodEffects(this);
  364. item->release();
  365. return 1;
  366. }
  367. }
  368. }
  369. if (!zStack || !zStack->zItem() || zStack->zItem()->isUsable())
  370. {
  371. cs.lock();
  372. if (target)
  373. {
  374. ItemSkill* selected = zSkill(typeId);
  375. if (!selected)
  376. {
  377. selected = Game::INSTANCE->zItemType(typeId)
  378. ->createDefaultItemSkill();
  379. selected->setItemTypeId(typeId);
  380. if (selected) skills.add(selected);
  381. }
  382. if (!selected)
  383. {
  384. selected = zSkill(ItemTypeEnum::PLAYER_HAND);
  385. selected->setItemTypeId(ItemTypeEnum::PLAYER_HAND);
  386. }
  387. bool result = target->interactItemSkillOnTarget(this,
  388. selected,
  389. !zStack || zStack->getSize() > 1 ? 0
  390. : (Item*)zStack->zItem());
  391. cs.unlock();
  392. return result;
  393. }
  394. cs.unlock();
  395. }
  396. else
  397. {
  398. useItem(ItemTypeEnum::PLAYER_HAND, 0, left);
  399. }
  400. }
  401. return 0;
  402. }
  403. void Entity::onTargetChange() {}
  404. bool Entity::interact(Item* zItem, Entity* zActor)
  405. {
  406. return false;
  407. }
  408. void Entity::addMovementFrame(MovementFrame& frame)
  409. {
  410. cs.lock();
  411. movements.add(frame);
  412. cs.unlock();
  413. Dimension* dim = Game::INSTANCE->zDimension(lastDimensionId);
  414. if (dim)
  415. {
  416. Chunk* chunk = dim->zChunk(lastChunkCenter);
  417. if (chunk)
  418. {
  419. NetworkMessage* message = new NetworkMessage();
  420. message->addressEntity(this);
  421. char* msg = new char[37];
  422. msg[0] = 0;
  423. *(float*)(msg + 1) = frame.direction.x;
  424. *(float*)(msg + 5) = frame.direction.y;
  425. *(float*)(msg + 9) = frame.direction.z;
  426. *(float*)(msg + 13) = frame.targetPosition.x;
  427. *(float*)(msg + 17) = frame.targetPosition.y;
  428. *(float*)(msg + 21) = frame.targetPosition.z;
  429. *(int*)(msg + 25) = frame.movementFlags;
  430. *(double*)(msg + 29) = frame.duration;
  431. message->setMessage(msg, 37);
  432. chunk->notifyObservers(message);
  433. }
  434. }
  435. faceDir = frame.direction;
  436. }
  437. void Entity::calculateTarget(Framework::Vec3<float> basePos,
  438. Framework::Vec3<float> direction,
  439. const Item* zItem)
  440. {
  441. Framework::Vec3<float> headPosition = basePos + faceOffset;
  442. int px = (int)floor(headPosition.x);
  443. int py = (int)floor(headPosition.y);
  444. int pz = (int)floor(headPosition.z);
  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. .abstandSq(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::prepareTick(const Dimension* zDimension) {}
  599. void Entity::tick(const Dimension* zDimension)
  600. {
  601. if (removed) return;
  602. if (placeBlockCooldown > 0)
  603. {
  604. placeBlockCooldown--;
  605. }
  606. placeBlockCooldown--;
  607. if (time.isMeasuring())
  608. {
  609. time.messungEnde();
  610. if (movements.getEintragAnzahl() > 0)
  611. {
  612. MovementFrame currentFrame = movements.get(0);
  613. double seconds = time.getSekunden();
  614. while (seconds > 0)
  615. {
  616. if (currentFrame.duration <= 0)
  617. {
  618. cs.lock();
  619. movements.remove(0);
  620. cs.unlock();
  621. if (movements.getEintragAnzahl() > 0)
  622. currentFrame = movements.get(0);
  623. else
  624. break;
  625. }
  626. double t = MIN(currentFrame.duration, seconds);
  627. // TODO: add collision detection to reduce cheating capability
  628. location += (currentFrame.targetPosition - location)
  629. * (float)(t / currentFrame.duration);
  630. currentFrame.duration -= t;
  631. seconds -= t;
  632. if (currentFrame.duration <= 0)
  633. {
  634. location = currentFrame.targetPosition;
  635. }
  636. }
  637. if (currentFrame.duration > 0) movements.set(currentFrame, 0);
  638. if (getStamina() <= getMaxStamina() - 0.0025f)
  639. {
  640. if (getThirst() > 0 && getHunger() > 0)
  641. {
  642. setStamina(getStamina() + 0.0025f);
  643. setHunger(getHunger() - 0.0005f);
  644. setThirst(getThirst() - 0.0015f);
  645. }
  646. }
  647. }
  648. else
  649. {
  650. if (getStamina() <= getMaxStamina() - 0.005f)
  651. {
  652. if (getThirst() > 0 && getHunger() > 0)
  653. {
  654. setStamina(getStamina() + 0.005f);
  655. setHunger(getHunger() - 0.001f);
  656. setThirst(getThirst() - 0.003f);
  657. }
  658. }
  659. }
  660. }
  661. time.messungStart();
  662. Framework::Punkt chunkCenter
  663. = Game::INSTANCE->getChunkCenter((int)location.x, (int)location.y);
  664. if (dimensionId != lastDimensionId || chunkCenter != lastChunkCenter)
  665. {
  666. Dimension* lastDimension = Game::INSTANCE->zDimension(lastDimensionId);
  667. Dimension* currentDimension = Game::INSTANCE->zDimension(dimensionId);
  668. Chunk* zCurrentChunk
  669. = currentDimension ? currentDimension->zChunk(chunkCenter) : 0;
  670. Chunk* zLastChunk
  671. = lastDimension ? lastDimension->zChunk(lastChunkCenter) : 0;
  672. if (lastDimensionId != -1)
  673. {
  674. if (zLastChunk)
  675. {
  676. zLastChunk->onEntityLeaves(
  677. this, lastDimensionId == dimensionId ? zCurrentChunk : 0);
  678. }
  679. }
  680. if (zCurrentChunk)
  681. {
  682. zCurrentChunk->onEntityEnters(
  683. this, lastDimensionId == dimensionId ? zLastChunk : 0);
  684. }
  685. lastDimensionId = dimensionId;
  686. lastChunkCenter = chunkCenter;
  687. }
  688. }
  689. void Entity::api(Framework::StreamReader* zRequest,
  690. NetworkMessage* zResponse,
  691. Entity* zSource)
  692. {
  693. char type;
  694. zRequest->lese(&type, 1);
  695. switch (type)
  696. {
  697. case 0: // request status bar state
  698. {
  699. char len;
  700. zRequest->lese(&len, 1);
  701. char* guiId = new char[(int)len + 1];
  702. zRequest->lese(guiId, len);
  703. guiId[(int)len] = 0;
  704. int processor;
  705. zRequest->lese((char*)&processor, 4);
  706. zResponse->addressUIElement(guiId, processor);
  707. statusBarObservable.addObserver(zSource, guiId, processor);
  708. char* msg = new char[33];
  709. msg[0] = 0;
  710. *(float*)(msg + 1) = getMaxHP();
  711. *(float*)(msg + 5) = getCurrentHP();
  712. *(float*)(msg + 9) = getMaxStamina();
  713. *(float*)(msg + 13) = getStamina();
  714. *(float*)(msg + 17) = getMaxHunger();
  715. *(float*)(msg + 21) = getHunger();
  716. *(float*)(msg + 25) = getMaxThirst();
  717. *(float*)(msg + 29) = getThirst();
  718. zResponse->setMessage(msg, 33);
  719. delete[] guiId;
  720. break;
  721. }
  722. case 1: // remove status bar observer
  723. {
  724. char len;
  725. zRequest->lese(&len, 1);
  726. char* guiId = new char[(int)len + 1];
  727. zRequest->lese(guiId, len);
  728. guiId[(int)len] = 0;
  729. int processor;
  730. zRequest->lese((char*)&processor, 4);
  731. statusBarObservable.removeObserver(zSource, guiId, processor);
  732. delete[] guiId;
  733. break;
  734. }
  735. case 2: // TODO: component request
  736. break;
  737. }
  738. }
  739. void Entity::onFall(float collisionSpeed)
  740. {
  741. if (collisionSpeed > 10)
  742. {
  743. setHP(this, 0, 0, getCurrentHP() - (collisionSpeed - 10.f) / 2.5f);
  744. }
  745. }
  746. Framework::XML::Element* Entity::getTargetUIML() const
  747. {
  748. return new Framework::XML::Element(
  749. Framework::Text(
  750. "<targetInfo><text id=\"type\" width=\"auto\" height=\"auto\">")
  751. + Game::INSTANCE->zEntityType(typeId)->getName()
  752. + "</text></targetInfo>");
  753. }
  754. void Entity::setChatSecurityLevel(int level)
  755. {
  756. chatSecurityLevel = level;
  757. }
  758. void Entity::setPosition(Framework::Vec3<float> pos)
  759. {
  760. location = pos;
  761. }
  762. void Entity::takeDamage(
  763. Entity* zSource, Item* zUsedItem, ItemSkill* zUsedSkill, float damage)
  764. {
  765. currentHP -= damage;
  766. if (currentHP <= 0)
  767. {
  768. currentHP = 0;
  769. onDeath(zSource, zUsedItem, zUsedSkill);
  770. }
  771. }
  772. void Entity::setHP(
  773. Entity* zActor, Item* zUsedItem, ItemSkill* zUsedSkill, float hp)
  774. {
  775. currentHP = MIN(MAX(hp, 0), maxHP);
  776. NetworkMessage* msg = new NetworkMessage();
  777. char* message = new char[9];
  778. message[0] = 1;
  779. *(float*)(message + 1) = getMaxHP();
  780. *(float*)(message + 5) = getCurrentHP();
  781. msg->setMessage(message, 9);
  782. notifyStatusBarObservers(msg);
  783. if (currentHP == 0)
  784. {
  785. onDeath(zActor, zUsedItem, zUsedSkill);
  786. }
  787. }
  788. void Entity::setStamina(float stamina)
  789. {
  790. this->stamina = MIN(MAX(stamina, 0), maxStamina);
  791. NetworkMessage* msg = new NetworkMessage();
  792. char* message = new char[9];
  793. message[0] = 2;
  794. *(float*)(message + 1) = getMaxStamina();
  795. *(float*)(message + 5) = getStamina();
  796. msg->setMessage(message, 9);
  797. notifyStatusBarObservers(msg);
  798. }
  799. void Entity::setHunger(float hunger)
  800. {
  801. this->hunger = MIN(MAX(hunger, 0), maxHunger);
  802. NetworkMessage* msg = new NetworkMessage();
  803. char* message = new char[9];
  804. message[0] = 3;
  805. *(float*)(message + 1) = getMaxHunger();
  806. *(float*)(message + 5) = getHunger();
  807. msg->setMessage(message, 9);
  808. notifyStatusBarObservers(msg);
  809. }
  810. void Entity::setThirst(float thirst)
  811. {
  812. this->thirst = MIN(MAX(thirst, 0), maxThirst);
  813. NetworkMessage* msg = new NetworkMessage();
  814. char* message = new char[9];
  815. message[0] = 4;
  816. *(float*)(message + 1) = getMaxThirst();
  817. *(float*)(message + 5) = getThirst();
  818. msg->setMessage(message, 9);
  819. notifyStatusBarObservers(msg);
  820. }
  821. void Entity::setGravityMultiplier(float multiplier)
  822. {
  823. gravityMultiplier = multiplier;
  824. }
  825. float Entity::getMaxHP() const
  826. {
  827. return maxHP;
  828. }
  829. float Entity::getCurrentHP() const
  830. {
  831. return currentHP;
  832. }
  833. float Entity::getStamina() const
  834. {
  835. return stamina;
  836. }
  837. float Entity::getMaxStamina() const
  838. {
  839. return maxStamina;
  840. }
  841. float Entity::getHunger() const
  842. {
  843. return hunger;
  844. }
  845. float Entity::getMaxHunger() const
  846. {
  847. return maxHunger;
  848. }
  849. float Entity::getThirst() const
  850. {
  851. return thirst;
  852. }
  853. float Entity::getMaxThirst() const
  854. {
  855. return maxThirst;
  856. }
  857. Framework::Vec3<float> Entity::getSpeed() const
  858. {
  859. return speed;
  860. }
  861. Framework::Vec3<float> Entity::getFaceDir() const
  862. {
  863. return faceDir;
  864. }
  865. Framework::Vec3<float> Entity::getPosition() const
  866. {
  867. return location;
  868. }
  869. float Entity::getGravityMultiplier() const
  870. {
  871. return gravityMultiplier;
  872. }
  873. float Entity::getJumpSpeed() const
  874. {
  875. return jumpSpeed;
  876. }
  877. void Entity::setJumpSpeed(float speed)
  878. {
  879. jumpSpeed = speed;
  880. }
  881. bool Entity::isRemoved() const
  882. {
  883. return removed;
  884. }
  885. const EntityType* Entity::zType() const
  886. {
  887. return Game::INSTANCE->zEntityType(typeId);
  888. }
  889. const ActionTarget* Entity::zTarget() const
  890. {
  891. return target;
  892. }
  893. int Entity::getId() const
  894. {
  895. return id;
  896. }
  897. bool Entity::hasDefaultModel() const
  898. {
  899. return 1;
  900. }
  901. ModelInfo* Entity::zSpecialModel() const
  902. {
  903. return 0;
  904. }
  905. float Entity::getMaxSpeed() const
  906. {
  907. return maxMovementSpeed;
  908. }
  909. bool Entity::isMoving() const
  910. {
  911. return movements.getEintragAnzahl() > 0;
  912. }
  913. int Entity::getChatSecurityLevel() const
  914. {
  915. return chatSecurityLevel;
  916. }
  917. Framework::Maybe<Framework::Punkt> Entity::getLastSavedChunkCenter() const
  918. {
  919. return lastSavedChunkCenter;
  920. }
  921. void Entity::setLastSavedChunkCenter(Framework::Punkt pos)
  922. {
  923. lastSavedChunkCenter = Framework::Maybe<Framework::Punkt>::of(pos);
  924. }
  925. void Entity::setRemoved()
  926. {
  927. removed = true;
  928. }
  929. double Entity::getHitDistance(
  930. Framework::Vec3<float> rayOrigin, Framework::Vec3<float> rayDirection) const
  931. {
  932. Framework::Mat4<float> rotMat
  933. = Framework::Mat4<float>::rotationX(-rotation.x)
  934. * Framework::Mat4<float>::rotationY(-rotation.y)
  935. * Framework::Mat4<float>::rotationZ(-rotation.z);
  936. Framework::Vec3<float> rotatedRayOrigin = rotMat * rayOrigin;
  937. Framework::Vec3<float> rotatedRayDirection = rotMat * rayDirection;
  938. rotatedRayDirection.normalize();
  939. if (rotatedRayDirection.x != 0)
  940. {
  941. float d;
  942. if (rotatedRayDirection.x > 0)
  943. {
  944. float border = getPosition().x - boundingBox.x;
  945. d = (border - rotatedRayOrigin.x) / rotatedRayDirection.x;
  946. }
  947. else if (rotatedRayDirection.x < 0)
  948. {
  949. float border = getPosition().x + boundingBox.x;
  950. d = (border - rotatedRayOrigin.x) / rotatedRayDirection.x;
  951. }
  952. if (d > 0)
  953. {
  954. Framework::Vec3<float> hitPoint
  955. = rotatedRayOrigin + rotatedRayDirection * d;
  956. if (hitPoint.y >= getPosition().y - boundingBox.y
  957. && hitPoint.y <= getPosition().y + boundingBox.y
  958. && hitPoint.z >= getPosition().z - boundingBox.z
  959. && hitPoint.z <= getPosition().z + boundingBox.z)
  960. {
  961. return d;
  962. }
  963. }
  964. }
  965. if (rotatedRayDirection.y != 0)
  966. {
  967. float d;
  968. if (rotatedRayDirection.y > 0)
  969. {
  970. float border = getPosition().y - boundingBox.y;
  971. d = (border - rotatedRayOrigin.y) / rotatedRayDirection.y;
  972. }
  973. else if (rotatedRayDirection.y < 0)
  974. {
  975. float border = getPosition().y + boundingBox.y;
  976. d = (border - rotatedRayOrigin.y) / rotatedRayDirection.y;
  977. }
  978. if (d > 0)
  979. {
  980. Framework::Vec3<float> hitPoint
  981. = rotatedRayOrigin + rotatedRayDirection * d;
  982. if (hitPoint.x >= getPosition().x - boundingBox.x
  983. && hitPoint.x <= getPosition().x + boundingBox.x
  984. && hitPoint.z >= getPosition().z - boundingBox.z
  985. && hitPoint.z <= getPosition().z + boundingBox.z)
  986. {
  987. return d;
  988. }
  989. }
  990. }
  991. if (rotatedRayDirection.z != 0)
  992. {
  993. float d;
  994. if (rotatedRayDirection.z > 0)
  995. {
  996. float border = getPosition().z - boundingBox.z;
  997. d = (border - rotatedRayOrigin.z) / rotatedRayDirection.z;
  998. }
  999. else if (rotatedRayDirection.z < 0)
  1000. {
  1001. float border = getPosition().z + boundingBox.z;
  1002. d = (border - rotatedRayOrigin.z) / rotatedRayDirection.z;
  1003. }
  1004. if (d > 0)
  1005. {
  1006. Framework::Vec3<float> hitPoint
  1007. = rotatedRayOrigin + rotatedRayDirection * d;
  1008. if (hitPoint.x >= getPosition().x - boundingBox.x
  1009. && hitPoint.x <= getPosition().x + boundingBox.x
  1010. && hitPoint.y >= getPosition().y - boundingBox.y
  1011. && hitPoint.y <= getPosition().y + boundingBox.y)
  1012. {
  1013. return d;
  1014. }
  1015. }
  1016. }
  1017. return NAN;
  1018. }