player.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. /*
  2. Minetest-c55
  3. Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. /*
  17. (c) 2010 Perttu Ahola <celeron55@gmail.com>
  18. */
  19. #include "player.h"
  20. #include "map.h"
  21. #include "connection.h"
  22. #include "constants.h"
  23. #include "utility.h"
  24. Player::Player():
  25. touching_ground(false),
  26. in_water(false),
  27. in_water_stable(false),
  28. swimming_up(false),
  29. craftresult_is_preview(true),
  30. hp(20),
  31. peer_id(PEER_ID_INEXISTENT),
  32. m_pitch(0),
  33. m_yaw(0),
  34. m_speed(0,0,0),
  35. m_position(0,0,0)
  36. {
  37. updateName("<not set>");
  38. resetInventory();
  39. }
  40. Player::~Player()
  41. {
  42. }
  43. void Player::resetInventory()
  44. {
  45. inventory.clear();
  46. inventory.addList("main", PLAYER_INVENTORY_SIZE);
  47. inventory.addList("craft", 9);
  48. inventory.addList("craftresult", 1);
  49. }
  50. // Y direction is ignored
  51. void Player::accelerate(v3f target_speed, f32 max_increase)
  52. {
  53. v3f d_wanted = target_speed - m_speed;
  54. d_wanted.Y = 0;
  55. f32 dl_wanted = d_wanted.getLength();
  56. f32 dl = dl_wanted;
  57. if(dl > max_increase)
  58. dl = max_increase;
  59. v3f d = d_wanted.normalize() * dl;
  60. m_speed.X += d.X;
  61. m_speed.Z += d.Z;
  62. //m_speed += d;
  63. #if 0 // old code
  64. if(m_speed.X < target_speed.X - max_increase)
  65. m_speed.X += max_increase;
  66. else if(m_speed.X > target_speed.X + max_increase)
  67. m_speed.X -= max_increase;
  68. else if(m_speed.X < target_speed.X)
  69. m_speed.X = target_speed.X;
  70. else if(m_speed.X > target_speed.X)
  71. m_speed.X = target_speed.X;
  72. if(m_speed.Z < target_speed.Z - max_increase)
  73. m_speed.Z += max_increase;
  74. else if(m_speed.Z > target_speed.Z + max_increase)
  75. m_speed.Z -= max_increase;
  76. else if(m_speed.Z < target_speed.Z)
  77. m_speed.Z = target_speed.Z;
  78. else if(m_speed.Z > target_speed.Z)
  79. m_speed.Z = target_speed.Z;
  80. #endif
  81. }
  82. void Player::serialize(std::ostream &os)
  83. {
  84. // Utilize a Settings object for storing values
  85. Settings args;
  86. args.setS32("version", 1);
  87. args.set("name", m_name);
  88. args.setFloat("pitch", m_pitch);
  89. args.setFloat("yaw", m_yaw);
  90. args.setV3F("position", m_position);
  91. args.setBool("craftresult_is_preview", craftresult_is_preview);
  92. args.setS32("hp", hp);
  93. args.writeLines(os);
  94. os<<"PlayerArgsEnd\n";
  95. inventory.serialize(os);
  96. }
  97. void Player::deSerialize(std::istream &is)
  98. {
  99. Settings args;
  100. for(;;)
  101. {
  102. if(is.eof())
  103. throw SerializationError
  104. ("Player::deSerialize(): PlayerArgsEnd not found");
  105. std::string line;
  106. std::getline(is, line);
  107. std::string trimmedline = trim(line);
  108. if(trimmedline == "PlayerArgsEnd")
  109. break;
  110. args.parseConfigLine(line);
  111. }
  112. //args.getS32("version");
  113. std::string name = args.get("name");
  114. updateName(name.c_str());
  115. m_pitch = args.getFloat("pitch");
  116. m_yaw = args.getFloat("yaw");
  117. m_position = args.getV3F("position");
  118. try{
  119. craftresult_is_preview = args.getBool("craftresult_is_preview");
  120. }catch(SettingNotFoundException &e){
  121. craftresult_is_preview = true;
  122. }
  123. try{
  124. hp = args.getS32("hp");
  125. }catch(SettingNotFoundException &e){
  126. hp = 20;
  127. }
  128. inventory.deSerialize(is);
  129. }
  130. /*
  131. RemotePlayer
  132. */
  133. #ifndef SERVER
  134. RemotePlayer::RemotePlayer(
  135. scene::ISceneNode* parent,
  136. IrrlichtDevice *device,
  137. s32 id):
  138. scene::ISceneNode(parent, (device==NULL)?NULL:device->getSceneManager(), id),
  139. m_text(NULL)
  140. {
  141. m_box = core::aabbox3d<f32>(-BS/2,0,-BS/2,BS/2,BS*2,BS/2);
  142. if(parent != NULL && device != NULL)
  143. {
  144. // ISceneNode stores a member called SceneManager
  145. scene::ISceneManager* mgr = SceneManager;
  146. video::IVideoDriver* driver = mgr->getVideoDriver();
  147. gui::IGUIEnvironment* gui = device->getGUIEnvironment();
  148. // Add a text node for showing the name
  149. wchar_t wname[1] = {0};
  150. m_text = mgr->addTextSceneNode(gui->getBuiltInFont(),
  151. wname, video::SColor(255,255,255,255), this);
  152. m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
  153. // Attach a simple mesh to the player for showing an image
  154. scene::SMesh *mesh = new scene::SMesh();
  155. { // Front
  156. scene::IMeshBuffer *buf = new scene::SMeshBuffer();
  157. video::SColor c(255,255,255,255);
  158. video::S3DVertex vertices[4] =
  159. {
  160. video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
  161. video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
  162. video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
  163. video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
  164. };
  165. u16 indices[] = {0,1,2,2,3,0};
  166. buf->append(vertices, 4, indices, 6);
  167. // Set material
  168. buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
  169. //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
  170. buf->getMaterial().setTexture(0, driver->getTexture(porting::getDataPath("player.png").c_str()));
  171. buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
  172. buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
  173. //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
  174. buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
  175. // Add to mesh
  176. mesh->addMeshBuffer(buf);
  177. buf->drop();
  178. }
  179. { // Back
  180. scene::IMeshBuffer *buf = new scene::SMeshBuffer();
  181. video::SColor c(255,255,255,255);
  182. video::S3DVertex vertices[4] =
  183. {
  184. video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
  185. video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
  186. video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
  187. video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
  188. };
  189. u16 indices[] = {0,1,2,2,3,0};
  190. buf->append(vertices, 4, indices, 6);
  191. // Set material
  192. buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
  193. //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
  194. buf->getMaterial().setTexture(0, driver->getTexture(porting::getDataPath("player_back.png").c_str()));
  195. buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
  196. buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
  197. buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
  198. // Add to mesh
  199. mesh->addMeshBuffer(buf);
  200. buf->drop();
  201. }
  202. m_node = mgr->addMeshSceneNode(mesh, this);
  203. mesh->drop();
  204. m_node->setPosition(v3f(0,0,0));
  205. }
  206. }
  207. RemotePlayer::~RemotePlayer()
  208. {
  209. if(SceneManager != NULL)
  210. ISceneNode::remove();
  211. }
  212. void RemotePlayer::updateName(const char *name)
  213. {
  214. Player::updateName(name);
  215. if(m_text != NULL)
  216. {
  217. wchar_t wname[PLAYERNAME_SIZE];
  218. mbstowcs(wname, m_name, strlen(m_name)+1);
  219. m_text->setText(wname);
  220. }
  221. }
  222. void RemotePlayer::move(f32 dtime, Map &map, f32 pos_max_d)
  223. {
  224. m_pos_animation_time_counter += dtime;
  225. m_pos_animation_counter += dtime;
  226. v3f movevector = m_position - m_oldpos;
  227. f32 moveratio;
  228. if(m_pos_animation_time < 0.001)
  229. moveratio = 1.0;
  230. else
  231. moveratio = m_pos_animation_counter / m_pos_animation_time;
  232. if(moveratio > 1.5)
  233. moveratio = 1.5;
  234. m_showpos = m_oldpos + movevector * moveratio;
  235. ISceneNode::setPosition(m_showpos);
  236. }
  237. #endif
  238. #ifndef SERVER
  239. /*
  240. LocalPlayer
  241. */
  242. LocalPlayer::LocalPlayer():
  243. m_sneak_node(32767,32767,32767),
  244. m_sneak_node_exists(false)
  245. {
  246. }
  247. LocalPlayer::~LocalPlayer()
  248. {
  249. }
  250. void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
  251. core::list<CollisionInfo> *collision_info)
  252. {
  253. v3f position = getPosition();
  254. v3f oldpos = position;
  255. v3s16 oldpos_i = floatToInt(oldpos, BS);
  256. /*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
  257. <<oldpos_i.Z<<")"<<std::endl;*/
  258. /*
  259. Calculate new position
  260. */
  261. position += m_speed * dtime;
  262. // Skip collision detection if a special movement mode is used
  263. bool free_move = g_settings.getBool("free_move");
  264. if(free_move)
  265. {
  266. setPosition(position);
  267. return;
  268. }
  269. /*
  270. Collision detection
  271. */
  272. // Player position in nodes
  273. v3s16 pos_i = floatToInt(position, BS);
  274. /*
  275. Check if player is in water (the oscillating value)
  276. */
  277. try{
  278. // If in water, the threshold of coming out is at higher y
  279. if(in_water)
  280. {
  281. v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS);
  282. in_water = content_liquid(map.getNode(pp).d);
  283. }
  284. // If not in water, the threshold of going in is at lower y
  285. else
  286. {
  287. v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS);
  288. in_water = content_liquid(map.getNode(pp).d);
  289. }
  290. }
  291. catch(InvalidPositionException &e)
  292. {
  293. in_water = false;
  294. }
  295. /*
  296. Check if player is in water (the stable value)
  297. */
  298. try{
  299. v3s16 pp = floatToInt(position + v3f(0,0,0), BS);
  300. in_water_stable = content_liquid(map.getNode(pp).d);
  301. }
  302. catch(InvalidPositionException &e)
  303. {
  304. in_water_stable = false;
  305. }
  306. /*
  307. Collision uncertainty radius
  308. Make it a bit larger than the maximum distance of movement
  309. */
  310. //f32 d = pos_max_d * 1.1;
  311. // A fairly large value in here makes moving smoother
  312. f32 d = 0.15*BS;
  313. // This should always apply, otherwise there are glitches
  314. assert(d > pos_max_d);
  315. float player_radius = BS*0.35;
  316. float player_height = BS*1.7;
  317. // Maximum distance over border for sneaking
  318. f32 sneak_max = BS*0.4;
  319. /*
  320. If sneaking, player has larger collision radius to keep from
  321. falling
  322. */
  323. /*if(control.sneak)
  324. player_radius = sneak_max + d*1.1;*/
  325. /*
  326. If sneaking, keep in range from the last walked node and don't
  327. fall off from it
  328. */
  329. if(control.sneak && m_sneak_node_exists)
  330. {
  331. f32 maxd = 0.5*BS + sneak_max;
  332. v3f lwn_f = intToFloat(m_sneak_node, BS);
  333. position.X = rangelim(position.X, lwn_f.X-maxd, lwn_f.X+maxd);
  334. position.Z = rangelim(position.Z, lwn_f.Z-maxd, lwn_f.Z+maxd);
  335. f32 min_y = lwn_f.Y + 0.5*BS;
  336. if(position.Y < min_y)
  337. {
  338. position.Y = min_y;
  339. if(m_speed.Y < 0)
  340. m_speed.Y = 0;
  341. }
  342. }
  343. /*
  344. Calculate player collision box (new and old)
  345. */
  346. core::aabbox3d<f32> playerbox(
  347. position.X - player_radius,
  348. position.Y - 0.0,
  349. position.Z - player_radius,
  350. position.X + player_radius,
  351. position.Y + player_height,
  352. position.Z + player_radius
  353. );
  354. core::aabbox3d<f32> playerbox_old(
  355. oldpos.X - player_radius,
  356. oldpos.Y - 0.0,
  357. oldpos.Z - player_radius,
  358. oldpos.X + player_radius,
  359. oldpos.Y + player_height,
  360. oldpos.Z + player_radius
  361. );
  362. /*
  363. If the player's feet touch the topside of any node, this is
  364. set to true.
  365. Player is allowed to jump when this is true.
  366. */
  367. touching_ground = false;
  368. /*std::cout<<"Checking collisions for ("
  369. <<oldpos_i.X<<","<<oldpos_i.Y<<","<<oldpos_i.Z
  370. <<") -> ("
  371. <<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z
  372. <<"):"<<std::endl;*/
  373. /*
  374. Go through every node around the player
  375. */
  376. for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
  377. for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
  378. for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
  379. {
  380. try{
  381. // Player collides into walkable nodes
  382. if(content_walkable(map.getNode(v3s16(x,y,z)).d) == false)
  383. continue;
  384. }
  385. catch(InvalidPositionException &e)
  386. {
  387. // Doing nothing here will block the player from
  388. // walking over map borders
  389. }
  390. core::aabbox3d<f32> nodebox = getNodeBox(v3s16(x,y,z), BS);
  391. /*
  392. See if the player is touching ground.
  393. Player touches ground if player's minimum Y is near node's
  394. maximum Y and player's X-Z-area overlaps with the node's
  395. X-Z-area.
  396. Use 0.15*BS so that it is easier to get on a node.
  397. */
  398. if(
  399. //fabs(nodebox.MaxEdge.Y-playerbox.MinEdge.Y) < d
  400. fabs(nodebox.MaxEdge.Y-playerbox.MinEdge.Y) < 0.15*BS
  401. && nodebox.MaxEdge.X-d > playerbox.MinEdge.X
  402. && nodebox.MinEdge.X+d < playerbox.MaxEdge.X
  403. && nodebox.MaxEdge.Z-d > playerbox.MinEdge.Z
  404. && nodebox.MinEdge.Z+d < playerbox.MaxEdge.Z
  405. ){
  406. touching_ground = true;
  407. }
  408. // If player doesn't intersect with node, ignore node.
  409. if(playerbox.intersectsWithBox(nodebox) == false)
  410. continue;
  411. /*
  412. Go through every axis
  413. */
  414. v3f dirs[3] = {
  415. v3f(0,0,1), // back-front
  416. v3f(0,1,0), // top-bottom
  417. v3f(1,0,0), // right-left
  418. };
  419. for(u16 i=0; i<3; i++)
  420. {
  421. /*
  422. Calculate values along the axis
  423. */
  424. f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]);
  425. f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]);
  426. f32 playermax = playerbox.MaxEdge.dotProduct(dirs[i]);
  427. f32 playermin = playerbox.MinEdge.dotProduct(dirs[i]);
  428. f32 playermax_old = playerbox_old.MaxEdge.dotProduct(dirs[i]);
  429. f32 playermin_old = playerbox_old.MinEdge.dotProduct(dirs[i]);
  430. /*
  431. Check collision for the axis.
  432. Collision happens when player is going through a surface.
  433. */
  434. /*f32 neg_d = d;
  435. f32 pos_d = d;
  436. // Make it easier to get on top of a node
  437. if(i == 1)
  438. neg_d = 0.15*BS;
  439. bool negative_axis_collides =
  440. (nodemax > playermin && nodemax <= playermin_old + neg_d
  441. && m_speed.dotProduct(dirs[i]) < 0);
  442. bool positive_axis_collides =
  443. (nodemin < playermax && nodemin >= playermax_old - pos_d
  444. && m_speed.dotProduct(dirs[i]) > 0);*/
  445. bool negative_axis_collides =
  446. (nodemax > playermin && nodemax <= playermin_old + d
  447. && m_speed.dotProduct(dirs[i]) < 0);
  448. bool positive_axis_collides =
  449. (nodemin < playermax && nodemin >= playermax_old - d
  450. && m_speed.dotProduct(dirs[i]) > 0);
  451. bool main_axis_collides =
  452. negative_axis_collides || positive_axis_collides;
  453. /*
  454. Check overlap of player and node in other axes
  455. */
  456. bool other_axes_overlap = true;
  457. for(u16 j=0; j<3; j++)
  458. {
  459. if(j == i)
  460. continue;
  461. f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]);
  462. f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]);
  463. f32 playermax = playerbox.MaxEdge.dotProduct(dirs[j]);
  464. f32 playermin = playerbox.MinEdge.dotProduct(dirs[j]);
  465. if(!(nodemax - d > playermin && nodemin + d < playermax))
  466. {
  467. other_axes_overlap = false;
  468. break;
  469. }
  470. }
  471. /*
  472. If this is a collision, revert the position in the main
  473. direction.
  474. */
  475. if(other_axes_overlap && main_axis_collides)
  476. {
  477. v3f old_speed = m_speed;
  478. m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i];
  479. position -= position.dotProduct(dirs[i]) * dirs[i];
  480. position += oldpos.dotProduct(dirs[i]) * dirs[i];
  481. if(collision_info)
  482. {
  483. // Report fall collision
  484. if(old_speed.Y < m_speed.Y - 0.1)
  485. {
  486. CollisionInfo info;
  487. info.t = COLLISION_FALL;
  488. info.speed = m_speed.Y - old_speed.Y;
  489. collision_info->push_back(info);
  490. }
  491. }
  492. }
  493. }
  494. } // xyz
  495. /*
  496. Check the nodes under the player to see from which node the
  497. player is sneaking from, if any.
  498. */
  499. {
  500. v3s16 pos_i_bottom = floatToInt(position - v3f(0,BS/2,0), BS);
  501. v2f player_p2df(position.X, position.Z);
  502. f32 min_distance_f = 100000.0*BS;
  503. // If already seeking from some node, compare to it.
  504. /*if(m_sneak_node_exists)
  505. {
  506. v3f sneaknode_pf = intToFloat(m_sneak_node, BS);
  507. v2f sneaknode_p2df(sneaknode_pf.X, sneaknode_pf.Z);
  508. f32 d_horiz_f = player_p2df.getDistanceFrom(sneaknode_p2df);
  509. f32 d_vert_f = fabs(sneaknode_pf.Y + BS*0.5 - position.Y);
  510. // Ignore if player is not on the same level (likely dropped)
  511. if(d_vert_f < 0.15*BS)
  512. min_distance_f = d_horiz_f;
  513. }*/
  514. v3s16 new_sneak_node = m_sneak_node;
  515. for(s16 x=-1; x<=1; x++)
  516. for(s16 z=-1; z<=1; z++)
  517. {
  518. v3s16 p = pos_i_bottom + v3s16(x,0,z);
  519. v3f pf = intToFloat(p, BS);
  520. v2f node_p2df(pf.X, pf.Z);
  521. f32 distance_f = player_p2df.getDistanceFrom(node_p2df);
  522. f32 max_axis_distance_f = MYMAX(
  523. fabs(player_p2df.X-node_p2df.X),
  524. fabs(player_p2df.Y-node_p2df.Y));
  525. if(distance_f > min_distance_f ||
  526. max_axis_distance_f > 0.5*BS + sneak_max + 0.1*BS)
  527. continue;
  528. try{
  529. // The node to be sneaked on has to be walkable
  530. if(content_walkable(map.getNode(p).d) == false)
  531. continue;
  532. // And the node above it has to be nonwalkable
  533. if(content_walkable(map.getNode(p+v3s16(0,1,0)).d) == true)
  534. continue;
  535. }
  536. catch(InvalidPositionException &e)
  537. {
  538. continue;
  539. }
  540. min_distance_f = distance_f;
  541. new_sneak_node = p;
  542. }
  543. bool sneak_node_found = (min_distance_f < 100000.0*BS*0.9);
  544. if(control.sneak && m_sneak_node_exists)
  545. {
  546. if(sneak_node_found)
  547. m_sneak_node = new_sneak_node;
  548. }
  549. else
  550. {
  551. m_sneak_node = new_sneak_node;
  552. m_sneak_node_exists = sneak_node_found;
  553. }
  554. /*
  555. If sneaking, the player's collision box can be in air, so
  556. this has to be set explicitly
  557. */
  558. if(sneak_node_found && control.sneak)
  559. touching_ground = true;
  560. }
  561. /*
  562. Set new position
  563. */
  564. setPosition(position);
  565. }
  566. void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d)
  567. {
  568. move(dtime, map, pos_max_d, NULL);
  569. }
  570. void LocalPlayer::applyControl(float dtime)
  571. {
  572. // Clear stuff
  573. swimming_up = false;
  574. // Random constants
  575. f32 walk_acceleration = 4.0 * BS;
  576. f32 walkspeed_max = 4.0 * BS;
  577. setPitch(control.pitch);
  578. setYaw(control.yaw);
  579. v3f move_direction = v3f(0,0,1);
  580. move_direction.rotateXZBy(getYaw());
  581. v3f speed = v3f(0,0,0);
  582. bool free_move = g_settings.getBool("free_move");
  583. bool fast_move = g_settings.getBool("fast_move");
  584. bool continuous_forward = g_settings.getBool("continuous_forward");
  585. if(free_move)
  586. {
  587. v3f speed = getSpeed();
  588. speed.Y = 0;
  589. setSpeed(speed);
  590. }
  591. // Whether superspeed mode is used or not
  592. bool superspeed = false;
  593. // If free movement and fast movement, always move fast
  594. if(free_move && fast_move)
  595. superspeed = true;
  596. // Auxiliary button 1 (E)
  597. if(control.aux1)
  598. {
  599. if(free_move)
  600. {
  601. // In free movement mode, aux1 descends
  602. v3f speed = getSpeed();
  603. if(fast_move)
  604. speed.Y = -20*BS;
  605. else
  606. speed.Y = -walkspeed_max;
  607. setSpeed(speed);
  608. }
  609. else
  610. {
  611. // If not free movement but fast is allowed, aux1 is
  612. // "Turbo button"
  613. if(fast_move)
  614. superspeed = true;
  615. }
  616. }
  617. if(continuous_forward)
  618. speed += move_direction;
  619. if(control.up)
  620. {
  621. if(continuous_forward)
  622. superspeed = true;
  623. else
  624. speed += move_direction;
  625. }
  626. if(control.down)
  627. {
  628. speed -= move_direction;
  629. }
  630. if(control.left)
  631. {
  632. speed += move_direction.crossProduct(v3f(0,1,0));
  633. }
  634. if(control.right)
  635. {
  636. speed += move_direction.crossProduct(v3f(0,-1,0));
  637. }
  638. if(control.jump)
  639. {
  640. if(free_move)
  641. {
  642. v3f speed = getSpeed();
  643. if(fast_move)
  644. speed.Y = 20*BS;
  645. else
  646. speed.Y = walkspeed_max;
  647. setSpeed(speed);
  648. }
  649. else if(touching_ground)
  650. {
  651. v3f speed = getSpeed();
  652. /*
  653. NOTE: The d value in move() affects jump height by
  654. raising the height at which the jump speed is kept
  655. at its starting value
  656. */
  657. speed.Y = 6.5*BS;
  658. setSpeed(speed);
  659. }
  660. // Use the oscillating value for getting out of water
  661. // (so that the player doesn't fly on the surface)
  662. else if(in_water)
  663. {
  664. v3f speed = getSpeed();
  665. speed.Y = 1.5*BS;
  666. setSpeed(speed);
  667. swimming_up = true;
  668. }
  669. }
  670. // The speed of the player (Y is ignored)
  671. if(superspeed)
  672. speed = speed.normalize() * walkspeed_max * 5.0;
  673. else if(control.sneak)
  674. speed = speed.normalize() * walkspeed_max / 3.0;
  675. else
  676. speed = speed.normalize() * walkspeed_max;
  677. f32 inc = walk_acceleration * BS * dtime;
  678. // Faster acceleration if fast and free movement
  679. if(free_move && fast_move)
  680. inc = walk_acceleration * BS * dtime * 10;
  681. // Accelerate to target speed with maximum increment
  682. accelerate(speed, inc);
  683. }
  684. #endif