<commit_before>/*
	OpenLieroX

	the LX56 physics

	code under LGPL
	created on 9/2/2008
*/

/*
 some references:
 
 LX56 projectile simulation:
 http://openlierox.svn.sourceforge.net/viewvc/openlierox/src/client/CClient_Game.cpp?revision=1&view=markup&pathrev=1
 
 
 */


#include "LieroX.h"
#include "ProfileSystem.h"
#include "Physics.h"
#include "CGameScript.h"
#include "Frame.h"
#include "MathLib.h"
#include "CWorm.h"
#include "Entity.h"
#include "CBonus.h"
#include "CClient.h"
#include "console.h"
#include "Debug.h"
#include "CServer.h"
#include "FlagInfo.h"
#include "ProjectileDesc.h"
#include "WeaponDesc.h"
#include "PhysicsLX56.h"


// defined in PhysicsLX56_Projectiles
void LX56_simulateProjectiles(Iterator<CProjectile*>::Ref projs);

// TODO: clean up this code!



class PhysicsLX56 : public PhysicsEngine {
public:
	bool m_inited;

// ---------
	PhysicsLX56() : m_inited(false) {}
	virtual ~PhysicsLX56() { uninitGame(); }

	virtual std::string name() { return "LX56 physics"; }

	virtual void initGame() { m_inited = true; }
	virtual void uninitGame() { m_inited = false; }
	virtual bool isInitialised() { return m_inited; }


// -----------------------------
// ------ worm -----------------

	// Check collisions with the level
	// HINT: it directly manipulates vPos!
	bool moveAndCheckWormCollision(AbsTime currentTime, float dt, CWorm* worm, CVec pos, CVec *vel, CVec vOldPos, int jump ) {
		static const int maxspeed2 = 10; // this should not be too high as we could run out of the cClient->getMap() without checking else

		// Can happen when starting a game
		if (!cClient->getMap())
			return false;

		// check if the vel is really too high (or infinity), in this case just ignore
		if( (*vel*dt*worm->speedFactor()).GetLength2() > (float)cClient->getMap()->GetWidth() * (float)cClient->getMap()->GetHeight() )
			return true;

		// If the worm is going too fast, divide the speed by 2 and perform 2 collision checks
		// TODO: is this still needed? we call this function with a fixed dt
		// though perhaps it is as with higher speed the way we have to check is longer
		if( (*vel * dt * worm->speedFactor()).GetLength2() > maxspeed2 && dt > 0.001f ) {
			dt /= 2;
			if(moveAndCheckWormCollision(currentTime, dt,worm,pos,vel,vOldPos,jump)) return true;
			return moveAndCheckWormCollision(currentTime, dt,worm,worm->getPos(),vel,vOldPos,jump);
		}

		bool wrapAround = cClient->getGameLobby()->features[FT_InfiniteMap];
		pos += *vel * dt * worm->speedFactor();
		if(wrapAround) {
			FMOD(pos.x, (float)cClient->getMap()->GetWidth());
			FMOD(pos.y, (float)cClient->getMap()->GetHeight());
		}
		worm->pos() = pos;
		
		
		int x = (int)pos.x;
		int y = (int)pos.y;
		short clip = 0; // 0x1=left, 0x2=right, 0x4=top, 0x8=bottom
		bool coll = false;
		bool check_needed = false;

		const uchar* gridflags = cClient->getMap()->getAbsoluteGridFlags();
		uint grid_w = cClient->getMap()->getGridWidth();
		uint grid_h = cClient->getMap()->getGridHeight();
		uint grid_cols = cClient->getMap()->getGridCols();
		if(y-4 < 0 || (uint)y+5 >= cClient->getMap()->GetHeight()
		|| x-3 < 0 || (uint)x+3 >= cClient->getMap()->GetWidth())
			check_needed = true; // we will check later, what to do here
		else if(grid_w < 7 || grid_h < 10 // this ensures, that this check is safe
		|| (gridflags[((y-4)/grid_h)*grid_cols + (x-3)/grid_w] & (PX_ROCK|PX_DIRT))
		|| (gridflags[((y+5)/grid_h)*grid_cols + (x-3)/grid_w] & (PX_ROCK|PX_DIRT))
		|| (gridflags[((y-4)/grid_h)*grid_cols + (x+3)/grid_w] & (PX_ROCK|PX_DIRT))
		|| (gridflags[((y+5)/grid_h)*grid_cols + (x+3)/grid_w] & (PX_ROCK|PX_DIRT)))
			check_needed = true;

		if(check_needed && y >= 0 && (uint)y < cClient->getMap()->GetHeight()) {
			for(x=-3;x<4;x++) {
				// Optimize: pixelflag++
				
				// Left side clipping
				if(!wrapAround && (pos.x+x <= 2)) {
					clip |= 0x01;
					worm->pos().x=( 5 );
					coll = true;
					if(fabs(vel->x) > 40)
						vel->x *=  -0.4f;
					else
						vel->x=(0);
					continue;
				}

				// Right side clipping
				if(!wrapAround && (pos.x+x >= cClient->getMap()->GetWidth())) {
					worm->pos().x=( (float)cClient->getMap()->GetWidth() - 5 );
					coll = true;
					clip |= 0x02;
					if(fabs(vel->x) > 40)
						vel->x *= -0.4f;
					else
						vel->x=(0);
					continue;
				}

				int posx = (int)pos.x + x; if(wrapAround) { posx %= (int)cClient->getMap()->GetWidth(); if(posx < 0) posx += cClient->getMap()->GetWidth(); }
				if(!(cClient->getMap()->GetPixelFlag(posx,y) & PX_EMPTY)) {
					coll = true;

					if(x<0) {
						clip |= 0x01;
						notes << "leftcl,posx:" << posx << ",pos.x:" << pos.x << ",x:" << x << ",w:" << cClient->getMap()->GetWidth() << endl;
						worm->pos().x=( posx+4 + cClient->getMap()->GetWidth() ) % cClient->getMap()->GetWidth();
					}
					else {
						clip |= 0x02;
						worm->pos().x=( posx-4 + cClient->getMap()->GetWidth() ) % cClient->getMap()->GetWidth();
					}

					// Bounce
					if(fabs(vel->x) > 30)
						vel->x *= -0.4f;
					else
						vel->x=(0);
				}
			}
		}

		worm->setOnGround( false );

		bool hit = false;
		x = (int)pos.x;

		if(check_needed && x >= 0 && (uint)x < cClient->getMap()->GetWidth()) {
			for(y=5;y>-5;y--) {<commit_msg>sorry, forgot to remove test output<commit_after>/*
	OpenLieroX

	the LX56 physics

	code under LGPL
	created on 9/2/2008
*/

/*
 some references:
 
 LX56 projectile simulation:
 http://openlierox.svn.sourceforge.net/viewvc/openlierox/src/client/CClient_Game.cpp?revision=1&view=markup&pathrev=1
 
 
 */


#include "LieroX.h"
#include "ProfileSystem.h"
#include "Physics.h"
#include "CGameScript.h"
#include "Frame.h"
#include "MathLib.h"
#include "CWorm.h"
#include "Entity.h"
#include "CBonus.h"
#include "CClient.h"
#include "console.h"
#include "Debug.h"
#include "CServer.h"
#include "FlagInfo.h"
#include "ProjectileDesc.h"
#include "WeaponDesc.h"
#include "PhysicsLX56.h"


// defined in PhysicsLX56_Projectiles
void LX56_simulateProjectiles(Iterator<CProjectile*>::Ref projs);

// TODO: clean up this code!



class PhysicsLX56 : public PhysicsEngine {
public:
	bool m_inited;

// ---------
	PhysicsLX56() : m_inited(false) {}
	virtual ~PhysicsLX56() { uninitGame(); }

	virtual std::string name() { return "LX56 physics"; }

	virtual void initGame() { m_inited = true; }
	virtual void uninitGame() { m_inited = false; }
	virtual bool isInitialised() { return m_inited; }


// -----------------------------
// ------ worm -----------------

	// Check collisions with the level
	// HINT: it directly manipulates vPos!
	bool moveAndCheckWormCollision(AbsTime currentTime, float dt, CWorm* worm, CVec pos, CVec *vel, CVec vOldPos, int jump ) {
		static const int maxspeed2 = 10; // this should not be too high as we could run out of the cClient->getMap() without checking else

		// Can happen when starting a game
		if (!cClient->getMap())
			return false;

		// check if the vel is really too high (or infinity), in this case just ignore
		if( (*vel*dt*worm->speedFactor()).GetLength2() > (float)cClient->getMap()->GetWidth() * (float)cClient->getMap()->GetHeight() )
			return true;

		// If the worm is going too fast, divide the speed by 2 and perform 2 collision checks
		// TODO: is this still needed? we call this function with a fixed dt
		// though perhaps it is as with higher speed the way we have to check is longer
		if( (*vel * dt * worm->speedFactor()).GetLength2() > maxspeed2 && dt > 0.001f ) {
			dt /= 2;
			if(moveAndCheckWormCollision(currentTime, dt,worm,pos,vel,vOldPos,jump)) return true;
			return moveAndCheckWormCollision(currentTime, dt,worm,worm->getPos(),vel,vOldPos,jump);
		}

		bool wrapAround = cClient->getGameLobby()->features[FT_InfiniteMap];
		pos += *vel * dt * worm->speedFactor();
		if(wrapAround) {
			FMOD(pos.x, (float)cClient->getMap()->GetWidth());
			FMOD(pos.y, (float)cClient->getMap()->GetHeight());
		}
		worm->pos() = pos;
		
		
		int x = (int)pos.x;
		int y = (int)pos.y;
		short clip = 0; // 0x1=left, 0x2=right, 0x4=top, 0x8=bottom
		bool coll = false;
		bool check_needed = false;

		const uchar* gridflags = cClient->getMap()->getAbsoluteGridFlags();
		uint grid_w = cClient->getMap()->getGridWidth();
		uint grid_h = cClient->getMap()->getGridHeight();
		uint grid_cols = cClient->getMap()->getGridCols();
		if(y-4 < 0 || (uint)y+5 >= cClient->getMap()->GetHeight()
		|| x-3 < 0 || (uint)x+3 >= cClient->getMap()->GetWidth())
			check_needed = true; // we will check later, what to do here
		else if(grid_w < 7 || grid_h < 10 // this ensures, that this check is safe
		|| (gridflags[((y-4)/grid_h)*grid_cols + (x-3)/grid_w] & (PX_ROCK|PX_DIRT))
		|| (gridflags[((y+5)/grid_h)*grid_cols + (x-3)/grid_w] & (PX_ROCK|PX_DIRT))
		|| (gridflags[((y-4)/grid_h)*grid_cols + (x+3)/grid_w] & (PX_ROCK|PX_DIRT))
		|| (gridflags[((y+5)/grid_h)*grid_cols + (x+3)/grid_w] & (PX_ROCK|PX_DIRT)))
			check_needed = true;

		if(check_needed && y >= 0 && (uint)y < cClient->getMap()->GetHeight()) {
			for(x=-3;x<4;x++) {
				// Optimize: pixelflag++
				
				// Left side clipping
				if(!wrapAround && (pos.x+x <= 2)) {
					clip |= 0x01;
					worm->pos().x=( 5 );
					coll = true;
					if(fabs(vel->x) > 40)
						vel->x *=  -0.4f;
					else
						vel->x=(0);
					continue;
				}

				// Right side clipping
				if(!wrapAround && (pos.x+x >= cClient->getMap()->GetWidth())) {
					worm->pos().x=( (float)cClient->getMap()->GetWidth() - 5 );
					coll = true;
					clip |= 0x02;
					if(fabs(vel->x) > 40)
						vel->x *= -0.4f;
					else
						vel->x=(0);
					continue;
				}

				int posx = (int)pos.x + x; if(wrapAround) { posx %= (int)cClient->getMap()->GetWidth(); if(posx < 0) posx += cClient->getMap()->GetWidth(); }
				if(!(cClient->getMap()->GetPixelFlag(posx,y) & PX_EMPTY)) {
					coll = true;

					if(x<0) {
						clip |= 0x01;
						worm->pos().x=( posx+4 + cClient->getMap()->GetWidth() ) % cClient->getMap()->GetWidth();
					}
					else {
						clip |= 0x02;
						worm->pos().x=( posx-4 + cClient->getMap()->GetWidth() ) % cClient->getMap()->GetWidth();
					}

					// Bounce
					if(fabs(vel->x) > 30)
						vel->x *= -0.4f;
					else
						vel->x=(0);
				}
			}
		}

		worm->setOnGround( false );

		bool hit = false;
		x = (int)pos.x;

		if(check_needed && x >= 0 && (uint)x < cClient->getMap()->GetWidth()) {
			for(y=5;y>-5;y--) {
{'fraction_non_alphanumeric': 0.19331071255453222, 'fraction_numerical': 0.02035870092098885, 'mean_word_length': 3.2435211846976553, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 161, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1045633', 'n_tokens_mistral': 4514, 'n_tokens_neox': 3822, 'n_words': 859}