Beispiel #1
0
bool CollisionVolume::testCollision(const VC3 &objectPosition, const VC3 &angles, CollisionData &collisionData, float epsilon)
{
	QUAT rotation = getRotation(angles);
	//rotation.MakeFromAngles(0, -yRotation, 0);
	
	Matrix tm;
	tm.CreateRotationMatrix(rotation);

	// Everything's relative etc
	VC3 rayOrigin = tm.GetTransformedVector(collisionData.rayOrigin - objectPosition) + objectPosition;
	VC3 rayDirection = tm.GetWithoutTranslation().GetTransformedVector(collisionData.rayDirection);

	if(!data->possibleCollision(objectPosition, collisionData))
		return false;
	if(!data->accurateCollision(objectPosition, collisionData, rayOrigin, rayDirection))
		return false;

	float collisionDistance = objectPosition.GetRangeTo(collisionData.rayOrigin);
	VC3 pos = tm.GetInverse().GetTransformedVector(collisionData.collisionPosition - objectPosition) + objectPosition;

	if(collisionData.hasCollision)
	if(collisionDistance > pos.GetRangeTo(collisionData.rayOrigin))
		return false;

	collisionData.rayLength = collisionDistance;
	collisionData.hasCollision = true;
	collisionData.collisionPosition = objectPosition;
	collisionData.objectData = data->data;

	return true;
}
		SharedModel(shared_ptr<IStorm3D_Model> model_, shared_ptr<IStorm3D_Model> fadeModel_, const std::string &bones_, const std::string &idleAnimation_)
		:	model(model_),
			fadeModel(fadeModel_),
			bones(bones_),
			idleAnimation(idleAnimation_),
			radius(0),
			radius2d(0)
		{
			boost::scoped_ptr<Iterator<IStorm3D_Model_Object *> > objectIterator(model->ITObject->Begin());
			for(; !objectIterator->IsEnd(); objectIterator->Next())
			{
				IStorm3D_Model_Object *object = objectIterator->GetCurrent();
				if(!object)
					continue;

				IStorm3D_Mesh *mesh = object->GetMesh();
				if(!mesh)
					continue;

				VC3 objectPosition = object->GetPosition();
				float objectDistance = objectPosition.GetLength();
				float distance = objectDistance + mesh->GetRadius();
				if(distance > radius)
					radius = distance;

				float meshRadius = mesh->GetRadius();
				if(meshRadius + objectDistance > radius2d)
					radius2d = meshRadius + objectDistance;
			}

			if(!bones.empty())
				model->LoadBones(bones.c_str());
		}
Beispiel #3
0
/*!
	\param screen_position screen position
	\param position_ position
	\param direction_ direction
*/
void Storm3D_Scene::GetEyeVectors(const VC2I &screen_position, Vector &position_, Vector &direction_)
{
	static const float NEAR_Z = 2.f;

	D3DXMATRIX pProjection;
	D3DXMATRIX pView;

	VC3 camera_up = camera.GetUpVec();
	VC3 camera_position = camera.GetPosition();
	VC3 camera_target = camera.GetTarget();
	
	D3DXMatrixLookAtLH(pView, camera_position, camera_target, camera_up);

	//RECT windowSize = { 0 };
	//GetClientRect(Storm3D2->window_handle, &windowSize);
	igios_unimplemented();
	Storm3D_SurfaceInfo ss = Storm3D2->GetScreenSize();
	float aspect=(float) ss.width / (float) ss.height;

	float fov = camera.GetFieldOfView();
	float vis_range = camera.GetVisibilityRange();

	VC3 pV;
	D3DXMatrixPerspectiveFovLH(pProjection,fov,aspect,1.0f,vis_range);

	pV.x = 1.0f;
	pV.y = 1.0f;
	pV.z = 1.0f;
	//pV.x =  ( ( ( 2.0f * (float)screen_position.x ) / windowSize.right  ) - 1 ) / pProjection._11;
	//pV.y = -( ( ( 2.0f * (float)screen_position.y ) / windowSize.bottom ) - 1 ) / pProjection._22;
	//pV.z =  1.0f;

	D3DXMATRIX m;
	D3DXMatrixInverse(m, NULL, pView);

	VC3 vPickRayDir;
	VC3 vPickRayOrig;

	vPickRayDir.x  = pV.x*m._11 + pV.y*m._21 + pV.z*m._31;
	vPickRayDir.y  = pV.x*m._12 + pV.y*m._22 + pV.z*m._32;
	vPickRayDir.z  = pV.x*m._13 + pV.y*m._23 + pV.z*m._33;
	vPickRayDir = vPickRayDir.GetNormalized();
	vPickRayOrig.x = m._41;
	vPickRayOrig.y = m._42;
	vPickRayOrig.z = m._43;

	vPickRayOrig+=vPickRayDir*NEAR_Z;

	direction_.x = vPickRayDir.x;
	direction_.y = vPickRayDir.y;
	direction_.z = vPickRayDir.z;
	position_.x = vPickRayOrig.x;
	position_.y = vPickRayOrig.y;
	position_.z = vPickRayOrig.z;
}
Beispiel #4
0
/*!
	\param x
	\param y
	\param dir
	\param origin
	\param near_z
*/
void Storm3D_Camera::getRayVector(int x, int y, VC3 &dir, VC3 &origin, float near_z)
{
	D3DXMATRIX pProjection;
	D3DXMATRIX pView;

	D3DXVECTOR3 upvec(this->upvec.x, this->upvec.y, this->upvec.z);

	D3DXVECTOR3 position(this->position.x, this->position.y, this->position.z);
	D3DXVECTOR3 target(this->target.x, this->target.y, this->target.z);
	D3DXMatrixLookAtLH(&pView, &position, &target, &upvec);

	float fov = this->GetFieldOfView();
	Storm3D_SurfaceInfo ss = Storm3D2->GetScreenSize();
	float aspect=(float) ss.width / (float) ss.height;
	float vis_range = this->GetVisibilityRange();

	VC3 pV;

	D3DXMatrixPerspectiveFovLH(&pProjection, fov, aspect, 1.0f, vis_range);

	pV.x = ( ( ( 2.0f * (float)x * ss.width / 1024 ) / ss.width  ) - 1 ) / pProjection._11;
	pV.y = ( ( ( 2.0f * (float)y * ss.height / 768 ) / ss.height ) - 1 ) / pProjection._22;
	pV.z = 1.0f;

	D3DXMATRIX m;
	D3DXMatrixInverse(&m, NULL, &pView);

	VC3 vPickRayDir;
	VC3 vPickRayOrig;

	vPickRayDir.x  = pV.x * m._11 + pV.y * m._21 + pV.z * m._31;
	vPickRayDir.y  = pV.x * m._12 + pV.y * m._22 + pV.z * m._32;
	vPickRayDir.z  = pV.x * m._13 + pV.y * m._23 + pV.z * m._33;
	vPickRayDir.Normalize();
	vPickRayOrig.x = m._41;
	vPickRayOrig.y = m._42;
	vPickRayOrig.z = m._43;

	vPickRayOrig += vPickRayDir * near_z;

	dir.x = vPickRayDir.x;
	dir.y = vPickRayDir.y;
	dir.z = vPickRayDir.z;
	origin.x = vPickRayOrig.x;
	origin.y = vPickRayOrig.y;
	origin.z = vPickRayOrig.z;
}
Beispiel #5
0
	void VisualEffect::moveBetween(const VC3 &position_, const VC3 &endPosition, const VC3 &rotation, float alpha, float scale)
	{
		if (visualObject == NULL)
			return;

		if (effectType->getType() == VisualEffectType::VISUALEFFECT_TYPE_RAY)
		{
			this->position = (position_ + endPosition) / 2;
			VC3 diffVec = endPosition - position_;
			float raylen = diffVec.GetLength();
			VC3 scalevec(1*scale,1*scale,raylen);
			visualObject->setScale(scalevec);
			visualObject->setVisibilityFactor(alpha);
		}
		visualObject->setPosition(this->position);
		visualObject->setRotation(rotation.x, rotation.y, rotation.z);
	}
Beispiel #6
0
void GravityPointParticleForce::calcForce(Vector& force, const Vector& pos, const Vector& vel) {
	VC3 diff = pos - m_point;
	VC3 diffNorm = diff.GetNormalized();
	float diffLenSq = diff.GetSquareLength();
	if (fabsf(diffLenSq) < 0.01f)
	{
		force.x = 0.0f;
		force.y = 0.0f;
		force.z = 0.0f;
	} else {
		// realistic gravity (bad)
		//force = -diffNorm * 0.001f * m_gravity / diffLenSq;
		// unrealisic gravity (better)
		float diffLen = sqrtf(diffLenSq);
		force = -diffNorm * 0.001f * m_gravity / diffLen;
	}
}
void ParticlePhysics::physicsExplosion(const VC3 &explosionPosition, float forceFactor, float radius)
{
	// added support for radius parameter --jpk
	// TODO: this implementation does not take radius into account when calculating forces... (probably should)
	float radiusSq = radius * radius;

	for(PhysicsActorList::iterator it = data->physicsActorList.begin(); it != data->physicsActorList.end(); ++it)
	{
		PhysicsActor *actor = *it;
		if(!actor)
			continue;

		VC3 velocity;
		if(actor->actor)
			actor->actor->getMassCenterPosition(velocity);
		else
			velocity = actor->position;

		velocity -= explosionPosition;
		float len = velocity.GetSquareLength();
		if(len > radiusSq)
			continue;
		len = sqrtf(len);

		velocity.y *= 1.3f;
		velocity.y += 1.0f;

		if(len > 0.01f)
		{
			velocity /= len;

			if(len < 1.5f)
				len = 1.5f;

			velocity /= len;
		}
		else
			velocity.y = 1.f;

		velocity *= 7.5f * forceFactor;
		//actor->sleepCounter = 1;
		actor->force += velocity;
		actor->forceUpdate = true;
	}
}
Beispiel #8
0
	void ProgressBar::run(const VC3 &playerPosition, float playerAngle,
		bool continueKeyPressed, bool interruptKeyPressed)
	{
		if (isProgressing())
		{
			// has player moved/rotated too much to interrupt the progress
			bool playerInterrupted = interruptKeyPressed;

			if (!continueKeyPressed)
				playerInterrupted = true;

			VC3 moved = playerPosition - this->progressPosition;
			if (moved.GetSquareLength() > PROGRESSBAR_PLAYER_MOVE_TRESHOLD*PROGRESSBAR_PLAYER_MOVE_TRESHOLD)
				playerInterrupted = true;

			float rotAngle = util::AngleRotationCalculator::getFactoredRotationForAngles(playerAngle, this->progressAngle, 0.0f);
			if (fabs(rotAngle) > PROGRESSBAR_PLAYER_ROTATE_TRESHOLD)
				playerInterrupted = true;

			if (playerInterrupted)
			{
				progressing = false;
				triggerInterrupted = true;
				visibilityLeftCounter = PROGRESSBAR_VISIBLE_AFTER_STOP;
			}

			if (!isDone())
			{
				timeDone++;
			} else {
				progressing = false;
				visibilityLeftCounter = PROGRESSBAR_VISIBLE_AFTER_STOP;
			}
		} else {
			if (visibilityLeftCounter > 0)
			{
				visibilityLeftCounter--;
				if (visibilityLeftCounter == 0)
				{
					visible = false;
				}
			}
		}
	}
		bool SphereCollision(const VC3 &pos, float radius, Storm3D_CollisionInfo &info, bool accurate)
		{
			if(pos.GetRangeTo(position) < radius + getRadius())
			{
				info.hit = true;
				return true;
			}

			return false;
		}
Frustum Storm3D_Camera::getFrustum() const
{
	if(!forcedOrthogonalProjection)
	{
		if(visplane_update_needed) 
			UpdateVisPlanes();

		Frustum result(pnormals, position, vis_range);
		return result;
	}
	else
	{
		Frustum ret;
		VC3 nor = target - position;
		nor.Normalize ();
		VC3 pn[5] = { nor, nor, nor, nor, nor };
		return Frustum(pn, position, 10000.0f);
	}
}
void CollisionFace::SphereCollision(const VC3 &position, float radius, Storm3D_CollisionInfo &colinfo, bool accurate)
{
	VC3 closest;
	getClosestPoint(position, vertex0, vertex1, vertex2, closest);

	float sqRange = closest.GetSquareRangeTo(position);
	if(sqRange < radius * radius && sqRange < colinfo.range * colinfo.range)
	{
		colinfo.hit = true;
		colinfo.range = sqrtf(sqRange);
		colinfo.position = closest;
		colinfo.plane_normal = plane.planenormal;
		colinfo.inside_amount = radius - colinfo.range;

		float planeRange = plane.GetPointRange(position);
		if(planeRange < 0)
			colinfo.plane_normal = -colinfo.plane_normal;
	}
}
	float getAmount(const VC3 &pos, float angle, const IStorm3D_Terrain &terrain, float rayHeight) const
	{
		float fovRadians = fov * (3.1415927f / 180.f);
		int index = int(RAY_AMOUNT * (angle + fovRadians) / (2.f * fovRadians));
		assert(index >= 0 && index < RAY_AMOUNT);

		float distance = pos.GetRangeTo(position);
		if(!lengthOk[index])
		{
			float rayAngle = -fovRadians + float(index) * ((2 * fovRadians) / (RAY_AMOUNT - 1));

			VC3 rayDir = direction;
			float x = rayDir.x;
			float z = rayDir.z;

			rayDir.x = x * cosf(rayAngle) + z * sinf(rayAngle);
			rayDir.y = 0;
			rayDir.z = -x * sinf(rayAngle) + z * cosf(rayAngle);
			rayDir.Normalize();

			Storm3D_CollisionInfo cInfo;
			ObstacleCollisionInfo oInfo;
			terrain.rayTrace(position + VC3(0,rayHeight,0) + (rayDir * .5f), rayDir, range, cInfo, oInfo, true, true);

			if(oInfo.hit && oInfo.hitAmount > 0)
				length[index] = oInfo.ranges[0];
			else if(cInfo.hit)
				length[index] = cInfo.range;
			else
				length[index] = range;

			lengthOk[index] = true;
		}

		if(distance > length[index])
			return 0;

		return 1.f - distance / range;
	}
void PointArrayParticleSystem::setParticleVelocity(Vector& vel, const Vector& dir, float speed, const GenParticleSystemEditables& eds) 
{
	
	if(m_parray.get()==NULL)
		return;
	
	bool forceDirection = !use_explosion && (eds.launchDirectionType == GenParticleSystemEditables::DIRECTION_EXPLOSION || eds.launchDirectionType == GenParticleSystemEditables::DIRECTION_NEGATIVE_EXPLOSION);
	if(m_eds->useNormalsAsDirection || forceDirection)
	{
		if(m_eds->useBinormalsAsDirection)
		{
			//VC3 up = VC3(0,1,0);
			VC3 up = VC3((rand() % 1000) / 1000.0f, (rand() % 1000) / 1000.0f, (rand() % 1000) / 1000.0f);
			VC3 binormal = up.GetCrossWith(m_parray->normals[m_index]);
			vel = binormal * speed;	
			m_rotation.RotateVector(vel);
		} else {
			vel = m_parray->normals[m_index] * speed;	
			m_rotation.RotateVector(vel);
		}
	}
	else
		vel = dir * speed;
}
Beispiel #14
0
	bool LineAreaChecker::isPointInsideLineArea(const VC3 &point, 
		const VC3 &lineStart, const VC3 &lineEnd, float lineWidth)
	{
		VC3 projPos = lineEnd - lineStart;
		float projPosLenSq = projPos.GetSquareLength();
		VC3 projPosNorm = VC3(0,0,0);
		if (projPosLenSq > 0.00001f)
		{
			projPosNorm = projPos.GetNormalized();
		}

		VC3 chkpos = point - lineStart;
		float chkposLen = chkpos.GetLength();

		VC3 hitAndUnitDiff = chkpos - projPos;
		float hitAndUnitDiffLenSq = hitAndUnitDiff.GetSquareLength();

		float lineRadiusSq = (float)(lineWidth * lineWidth);

		if (hitAndUnitDiffLenSq < lineRadiusSq)
		{
			return true;
		}

		if (chkposLen * chkposLen < projPosLenSq)
		{
			VC3 pipedPos = projPosNorm * chkposLen;
			VC3 posdiff = chkpos - pipedPos;

			if (posdiff.GetSquareLength() < lineRadiusSq)
			{
				return true;
			}
		}

		return false;
	}
float SpotLightCalculator::getLightAmount(const VC3 &position, const IStorm3D_Terrain &terrain, float rayHeight) const
{
	float squareRange = position.GetSquareRangeTo(data->position);
	if(squareRange > data->squareRange)
		return 0;

	VC2 pdir(position.x - data->position.x, position.z - data->position.z);
	VC2 sdir(data->direction.x, data->direction.z);

	float pAngle = pdir.CalculateAngle();
	float sAngle = sdir.CalculateAngle();
	float diff = pAngle - sAngle;
	//assert(diff

	if(diff < -3.1415f)
		diff += 3.1415f * 2;
	else if(diff > 3.1415f)
		diff -= 3.1415f * 2;

	if(fabsf(diff) / 3.1415f * 180.f > data->fov)
		return 0;

	return data->getAmount(position, -diff, terrain, rayHeight);
}
	void PositionScripting::process(util::ScriptProcess *sp, 
		int command, int intData, char *stringData, ScriptLastValueType *lastValue, 
		GameScriptData *gsd, Game *game)
	{
		switch(command)
		{
		case GS_CMD_SETPOSITION:
			{
				VC3 tmp(0,0,0);
				if (gs_coordinate_param(game->gameMap, stringData, &tmp))
				{
					float x = tmp.x;
					float y = tmp.z;
					game->gameMap->keepWellInScaledBoundaries(&x, &y);
					gsd->position = VC3(
						x, game->gameMap->getScaledHeightAt(x,y), y);
				} else {
					sp->error("PositionScripting::process - Missing or bad setPosition parameter.");
				}
			}
			break;

		case GS_CMD_POSITIONRANDOMOFFSET:
			if (intData > 0)
			{
				int o1 = (game->gameRandom->nextInt() % (intData * 20 + 10)) - intData*10;
				int o2 = (game->gameRandom->nextInt() % (intData * 20 + 10)) - intData*10;
				int o3 = (game->gameRandom->nextInt() % (intData * 20 + 10)) - intData*10;
				gsd->position.x += (float)o1 * 0.1f;
				gsd->position.y += (float)o2 * 0.1f;
				gsd->position.z += (float)o3 * 0.1f;
			} else {
				sp->warning("PositionScripting::process - positionRandomOffset with zero parameter.");
				lastValue = 0;
			}
			break;

		case GS_CMD_MOVEPOSITIONZ:
			gsd->position.z += (float)intData / 100.0f;
			break;

		case GS_CMD_MOVEPOSITIONX:
			gsd->position.x += (float)intData / 100.0f;
			break;

		case GS_CMD_MOVEPOSITIONZFLOAT:
			{
				float floatData = *((float *)(&intData));
				gsd->position.z += floatData;
			}
			break;

		case GS_CMD_MOVEPOSITIONXFLOAT:
			{
				float floatData = *((float *)(&intData));
				gsd->position.x += floatData;
			}
			break;

		case GS_CMD_GETPOSITIONX:
			*lastValue = (int)gsd->position.x;
			break;

		case GS_CMD_GETPOSITIONZ:
			*lastValue = (int)gsd->position.z;
			break;
							 
		case GS_CMD_GETPOSITIONHEIGHT:
			*lastValue = (int)gsd->position.y;
			break;
							 
		case GS_CMD_GETACCURATEPOSITIONX:
			*lastValue = (int)(gsd->position.x * 1000.0f);
			break;

		case GS_CMD_GETACCURATEPOSITIONZ:
			*lastValue = (int)(gsd->position.z * 1000.0f);
			break;
							 
		case GS_CMD_SETPOSITIONHEIGHT:
			if (stringData != NULL)
			{
				gsd->position.y = (float)atof(stringData);
			} else {
				sp->error("PositionScripting::process - Missing setPositionHeight parameter.");
			}
			break;

		case GS_CMD_SETPOSITIONHEIGHTONGROUND:
			{
				float x = gsd->position.x;
				float y = gsd->position.z;
				game->gameMap->keepWellInScaledBoundaries(&x, &y);
				gsd->position = VC3(
					x, game->gameMap->getScaledHeightAt(x,y), y);
			}
			break;

		case GS_CMD_POSITIONACCURATERANDOMOFFSET:
			if (intData > 0)
			{
				// intData values in cm
				int o1 = (game->gameRandom->nextInt() % (intData * 20 + 10)) - intData*10;
				int o2 = (game->gameRandom->nextInt() % (intData * 20 + 10)) - intData*10;
				int o3 = (game->gameRandom->nextInt() % (intData * 20 + 10)) - intData*10;
				gsd->position.x += (float)o1 * 0.1f * 0.01f;
				gsd->position.y += (float)o2 * 0.1f * 0.01f;
				gsd->position.z += (float)o3 * 0.1f * 0.01f;
			} else {
				sp->warning("PositionScripting::process - positionRandomOffset with zero parameter.");
				lastValue = 0;
			}
			break;

		case GS_CMD_MOVEPOSITIONHEIGHT:
			gsd->position.y += (float)intData / 100.0f;
			break;

		case GS_CMD_SETSECONDARYPOSITION:
			gsd->secondaryPosition = gsd->position;
			break;

		case GS_CMD_GETSECONDARYPOSITION:
			gsd->position = gsd->secondaryPosition;
			break;

		case GS_CMD_SETPOSITIONX:
			gsd->position.x = (float)*lastValue;
			break;

		case GS_CMD_SETPOSITIONZ:
			gsd->position.z = (float)*lastValue;
			break;
							 
		case GS_CMD_SETACCURATEPOSITIONX:
			gsd->position.x = (float)*lastValue / 1000.0f;
			break;

		case GS_CMD_SETACCURATEPOSITIONZ:
			gsd->position.z = (float)*lastValue / 1000.0f;
			break;

		case GS_CMD_setAccuratePositionHeight:
			gsd->position.y = (float)*lastValue / 1000.0f;
			break;

		case GS_CMD_getAccuratePositionHeight:
			*lastValue = (int)(gsd->position.y * 1000.0f);
			break;

		case GS_CMD_PUSHGLOBALTEMPPOSITION:
			if (gs_global_temp_position_used)
			{
				sp->warning("PositionScripting::process - pushGlobalTempPosition, stack full.");
			}
			gs_global_temp_position_used = true;
			gs_global_temp_position = gsd->position;
			break;
							 
		case GS_CMD_POPGLOBALTEMPPOSITION:
			if (!gs_global_temp_position_used)
			{
				sp->warning("PositionScripting::process - popGlobalTempPosition, stack empty.");
			}
			gsd->position = gs_global_temp_position;
			gs_global_temp_position_used = false;
			gs_global_temp_position = VC3(0,0,0);
			break;
							 
		case GS_CMD_MOVEPOSITIONTOANGLEVALUE:
			{
				float angle = (float)(*lastValue);
				if (angle < 0) angle += 360;
				if (angle >= 360) angle -= 360;
				float amount= (float)intData / 100.0f;
				gsd->position.x += -amount * sinf(UNIT_ANGLE_TO_RAD(angle));
				gsd->position.z += -amount * cosf(UNIT_ANGLE_TO_RAD(angle));
			}
			break;

		case GS_CMD_ISPOSITIONINSIDEBUILDING:
			{
				VC3 pos = gsd->position;
				int x = game->gameMap->scaledToPathfindX(pos.x);
				int y = game->gameMap->scaledToPathfindY(pos.z);
				if (game->gameMap->isWellInScaledBoundaries(pos.x, pos.z))
				{
					if (game->gameMap->getAreaMap()->isAreaAnyValue(x, y, AREAMASK_INBUILDING))
						*lastValue = 1;
					else
						*lastValue = 0;
				} else {
					*lastValue = 0;
				}
			}
			break;

		case GS_CMD_isPositionBlockedByUnmoving:
			{
				VC3 pos = gsd->position;
				int x = game->gameMap->scaledToPathfindX(pos.x);
				int y = game->gameMap->scaledToPathfindY(pos.z);
				if (game->gameMap->isWellInScaledBoundaries(pos.x, pos.z))
				{
					if (game->gameMap->getObstacleHeight(x, y) > 0
						&& !game->gameMap->isMovingObstacle(x, y))
						*lastValue = 1;
					else
						*lastValue = 0;
				} else {
					*lastValue = 0;
				}
			}
			break;

		case GS_CMD_isPositionBlockedByUnmovingOrDoor:
			{
				VC3 pos = gsd->position;
				int x = game->gameMap->scaledToPathfindX(pos.x);
				int y = game->gameMap->scaledToPathfindY(pos.z);
				if (game->gameMap->isWellInScaledBoundaries(pos.x, pos.z))
				{
					// HACK: rounded moving obstacles are actually doors
					if (game->gameMap->getObstacleHeight(x, y) > 0
						&& (!game->gameMap->isMovingObstacle(x, y)
						|| game->gameMap->isRoundedObstacle(x, y)))
						*lastValue = 1;
					else
						*lastValue = 0;
				} else {
					*lastValue = 0;
				}
			}
			break;

		case GS_CMD_isPositionBlockedByMoving:
			{
				VC3 pos = gsd->position;
				int x = game->gameMap->scaledToPathfindX(pos.x);
				int y = game->gameMap->scaledToPathfindY(pos.z);
				if (game->gameMap->isWellInScaledBoundaries(pos.x, pos.z))
				{
					if (game->gameMap->getObstacleHeight(x, y) > 0
						&& game->gameMap->isMovingObstacle(x, y))
						*lastValue = 1;
					else
						*lastValue = 0;
				} else {
					*lastValue = 0;
				}
			}
			break;

		case GS_CMD_setPositionVariable:
			if (stringData != NULL)
			{
				bool success = sp->getScript()->setGlobalPositionVariableValue(stringData, gsd->position.x, gsd->position.y, gsd->position.z);
				if (!success)
				{
					sp->error("PositionScripting::process - setPositionVariable, failed to set position variable value (variable does not exist or type mismatch).");
					sp->debug(stringData);
				}
			} else {
				sp->error("PositionScripting::process - setPositionVariable parameter missing, position variable name expected.");
			}
			break;

		case GS_CMD_getPositionVariable:
			if (stringData != NULL)
			{				
				float tmpx, tmpy, tmpz;
				bool success = sp->getScript()->getGlobalPositionVariableValue(stringData, &tmpx, &tmpy, &tmpz);
				if (success)
				{
					gsd->position = VC3(tmpx, tmpy, tmpz);
				} else {
					sp->error("PositionScripting::process - getPositionVariable, failed to get position variable value (variable does not exist or type mismatch).");
					sp->debug(stringData);
				}
			} else {
				sp->error("PositionScripting::process - getPositionVariable parameter missing, position variable name expected.");
			}
			break;

		case GS_CMD_addPositionVariableToPosition:
			if (stringData != NULL)
			{				
				float tmpx, tmpy, tmpz;
				bool success = sp->getScript()->getGlobalPositionVariableValue(stringData, &tmpx, &tmpy, &tmpz);
				if (success)
				{
					gsd->position += VC3(tmpx, tmpy, tmpz);
				} else {
					sp->error("PositionScripting::process - addPositionVariableToPosition, failed to get position variable value (variable does not exist or type mismatch).");
					sp->debug(stringData);
				}
			} else {
				sp->error("PositionScripting::process - addPositionVariableToPosition parameter missing, position variable name expected.");
			}
			break;

		case GS_CMD_setPositionKeepingHeight:
			{
				VC3 tmp(0,0,0);
				if (gs_coordinate_param(game->gameMap, stringData, &tmp))
				{
					gsd->position.x = tmp.x;
					gsd->position.y = tmp.y;
				} else {
					sp->error("PositionScripting::process - Missing or bad setPositionKeepingHeight parameter.");
				}
			}
			break;

		case GS_CMD_setPositionXToFloat:
			{
				float floatData = *((float *)&intData);
				gsd->position.x = floatData;
			}
			break;

		case GS_CMD_setPositionZToFloat:
			{
				float floatData = *((float *)&intData);
				gsd->position.z = floatData;
			}
			break;

		case GS_CMD_rayTraceToSecondaryPosition:
			{
				VC3 middle_pos = (gsd->secondaryPosition + gsd->position) * 0.5f;
				VC3 dir = gsd->secondaryPosition - gsd->position;
				float length = dir.GetLength();
				dir *= 1.0f / length;

				bool no_units = stringData && strstr(stringData, "no_units");

				// disable collision for units
				if(no_units)
				{
					IUnitListIterator *iter = game->units->getNearbyAllUnits(middle_pos, length * length);
					while (iter->iterateAvailable())
					{
						Unit *u = iter->iterateNext();
						if(u && u->getVisualObject())
						{
							u->getVisualObject()->setCollidable(false);
						}
					}
					delete iter;
				}

				// raycast
				*lastValue = 0;
				if(game && game->getGameScene())
				{
					GameCollisionInfo cinfo;
					game->getGameScene()->rayTrace(gsd->position, dir, length, cinfo, true, false);
					if(cinfo.hit)
					{
						gsd->position = cinfo.position;
						*lastValue = 1;
					}
				}

				// re-enable collision for units
				if(no_units)
				{
					IUnitListIterator *iter = game->units->getNearbyAllUnits(middle_pos, length * length);
					while (iter->iterateAvailable())
					{
						Unit *u = iter->iterateNext();
						if(u && u->getVisualObject())
						{
							u->getVisualObject()->setCollidable(true);
						}
					}
					delete iter;
				}
			}
			break;

		default:
			sp->error("PositionScripting::process - Unknown command.");
			assert(0);
		}
	}
Beispiel #17
0
void PhysicsLib::updateVisualization(const VC3 &cameraPosition, float range, bool forceUpdate)
{
	bool visualizeCollisionShapes = data->featureMap[PhysicsLib::VISUALIZE_COLLISION_SHAPES];
	bool visualizeDynamic = data->featureMap[PhysicsLib::VISUALIZE_DYNAMIC];
	bool visualizeStatic = data->featureMap[PhysicsLib::VISUALIZE_STATIC];
	bool visualizeCollisionContacts = data->featureMap[PhysicsLib::VISUALIZE_COLLISION_CONTACTS];
	bool visualizeFluids = data->featureMap[PhysicsLib::VISUALIZE_FLUIDS];
	bool visualizeJoints = data->featureMap[PhysicsLib::VISUALIZE_JOINTS];
	bool visualizeCCD = data->featureMap[PhysicsLib::VISUALIZE_CCD];

	if (forceUpdate
		|| visualizeCollisionShapes
		|| visualizeDynamic
		|| visualizeStatic
		|| visualizeCollisionContacts
		|| visualizeFluids
		|| visualizeJoints
		|| visualizeCCD)
	{
		// (do the update)
	} else {
		// do not unnecessarily do this stuff!
		return;
	}

	float rangeSq = range * range;

	int actorAmount = data->scene->getNbActors();
	NxActor **actorArray = data->scene->getActors();

	if(visualizeCollisionShapes || visualizeStatic || visualizeCollisionContacts)
		data->sdk->setParameter(NX_VISUALIZE_COLLISION_SHAPES, 1);
	else
		data->sdk->setParameter(NX_VISUALIZE_COLLISION_SHAPES, 0);

	if(visualizeDynamic)
		data->sdk->setParameter(NX_VISUALIZE_BODY_MASS_AXES, 1);
	else
		data->sdk->setParameter(NX_VISUALIZE_BODY_MASS_AXES, 0);

	data->sdk->setParameter(NX_VISUALIZE_CONTACT_NORMAL, visualizeCollisionContacts);
	data->sdk->setParameter(NX_VISUALIZE_CONTACT_FORCE, visualizeCollisionContacts);
	data->sdk->setParameter(NX_VISUALIZE_CONTACT_POINT, visualizeCollisionContacts);

	data->sdk->setParameter(NX_VISUALIZE_COLLISION_SKELETONS, visualizeCCD);	

	for(int i = 0; i < actorAmount; ++i)
	{
		NxActor *actor = actorArray[i];
		if(!actor)
			continue;

		NxVec3 nxpos = actor->getGlobalPosition();
		VC3 pos(nxpos.x, nxpos.y, nxpos.z);
		VC3 diff = (pos - cameraPosition);
		diff.y = 0; // ignore height

		bool inRange = false;		
		if (diff.GetSquareLength() < rangeSq)
			inRange = true;

		if(actor->isDynamic())
		{
			//if(visualizeDynamic && inRange)
			if(visualizeDynamic)
				actor->raiseBodyFlag(NX_BF_VISUALIZATION);
			else
				actor->clearBodyFlag(NX_BF_VISUALIZATION);
		}

		int shapeAmount = actor->getNbShapes();
		NxShape *const*shapes = actor->getShapes();

		while(shapeAmount--)
		{
			NxShape *shape = shapes[shapeAmount];

			if(actor->isDynamic())
			{
				//if(visualizeCollisionShapes && inRange)
				if(visualizeCollisionShapes)
					shape->setFlag(NX_SF_VISUALIZATION, true);
				else
					shape->setFlag(NX_SF_VISUALIZATION, false);
			}
			else
			{
				if(visualizeStatic && !shape->isHeightField() && inRange)
					shape->setFlag(NX_SF_VISUALIZATION, true);
				else
					shape->setFlag(NX_SF_VISUALIZATION, false);
			}
		}
	}
}
Beispiel #18
0
	bool ReconChecker::isReconAvailableAtPosition(Game *game, int player, const VC3 &position)
	{
		LinkedList *ulist = game->units->getAllUnits();
		LinkedListIterator iter = LinkedListIterator(ulist);

		while (iter.iterateAvailable())		
		{
			Unit *u = (Unit *)iter.iterateNext();
			
			// unit is friendly towards player?
			// (but player does not need to be friendly towards the unit ;)
			if (u->isActive() && !u->isDestroyed()				
				&& !game->isHostile(u->getOwner(), player)
				&& u->getReconValue() > 0
				&& u->getMoveState() != Unit::UNIT_MOVE_STATE_UNCONSCIOUS)
			{
				VC3 rayStartPosition = u->getPosition() + VC3(0, 2.0f, 0);
				VC3 target = position;
				float terrainHeight = game->gameMap->getScaledHeightAt(target.x, target.z);
				if (target.y < terrainHeight + 2.0f) target.y = terrainHeight + 2.0f;
				VC3 dir = target - rayStartPosition;
				float dirLen = dir.GetLength();
				dir.Normalize();

				if (dirLen > u->getUnitType()->getVisionRange() + 2.0f)
				{
					continue;
				}

				// TEMP!
				// ignore all small own units (1.5m)...
				// except the one we're trying to hit
				LinkedList *oul = game->units->getOwnedUnits(u->getOwner());
				LinkedListIterator iter = LinkedListIterator(oul);
				while (iter.iterateAvailable())
				{
					Unit *ou = (Unit *)iter.iterateNext();
					if (ou != u && ou->getUnitType()->getSize() <= 1.5f)
						ou->getVisualObject()->setCollidable(false);
				}

				// disable collision check for this unit
				u->getVisualObject()->setCollidable(false);

				GameCollisionInfo cinfo;
				game->getGameScene()->rayTrace(rayStartPosition, dir, (float)dirLen, cinfo, false, true);

				// collision check back
				u->getVisualObject()->setCollidable(true);				

				// TEMP!
				// restore them all...
				oul = game->units->getOwnedUnits(u->getOwner());
				iter = LinkedListIterator(oul);
				while (iter.iterateAvailable())
				{
					Unit *ou = (Unit *)iter.iterateNext();
					if (ou != u && ou->getUnitType()->getSize() <= 1.5f)
						ou->getVisualObject()->setCollidable(true);
				}

				if (cinfo.hit)
				{
					// 4 meters max dist.
					if (cinfo.range >= dirLen - 4.0f)
					{
						return true;
					}
				} else {
					return true;
				}
			}
		}
		return false;
	}
Beispiel #19
0
	void VisualEffect::init(IPointableObject *object, IPointableObject *origin,
		const VC3 &position, const VC3 &endPosition, const VC3 &rotation,
		int muzzleFlashBarrelNumber)
	{
		// make sure this is called only once.
		assert(visualObject == NULL);

		// set the object we want to follow...
		if (effectType->getFollow() == VisualEffectType::VISUALEFFECT_FOLLOW_NONE)
		{
			follow = NULL;
		} else {
			if (effectType->getFollow() == VisualEffectType::VISUALEFFECT_FOLLOW_OBJECT)
			{
				follow = object;
			} else {
				follow = origin;
			}
		}

		// visual object...
		visualObject = effectType->getNewVisualObject();

		if (effectType->getType() == VisualEffectType::VISUALEFFECT_TYPE_MUZZLEFLASH)
		{
			// special case: muzzleflash
			if (visualObject != NULL && follow != NULL)
			{
				Muzzleflasher::createMuzzleflash(follow, visualObject, muzzleFlashBarrelNumber);
				visualObject->setInScene(false);
			} else {
				//Logger::getInstance()->error("VisualEffect::init - Null visualObject or follow unit for muzzleflash.");
			}

			this->position = position;
			return;
		}

		if (effectType->getType() == VisualEffectType::VISUALEFFECT_TYPE_EJECT)
		{
			this->position = position;
			return;
		}

		// normal and ray visualeffects...

		visualObject->setCollidable(false);
		visualObject->setInScene(true);

		// set position, rotation and scale based on type and the 
		// given parameters...
		if (effectType->getType() == VisualEffectType::VISUALEFFECT_TYPE_NORMAL)
		{
			this->position = position;
		}
		if (effectType->getType() == VisualEffectType::VISUALEFFECT_TYPE_RAY)
		{
			this->position = (position + endPosition) / 2;
			VC3 diffVec = endPosition - position;
			float raylen = diffVec.GetLength();
			VC3 scale(1,1,raylen);
			visualObject->setScale(scale);
		}
		if (effectType->getType() == VisualEffectType::VISUALEFFECT_TYPE_NORMAL)
		{
			this->position = position;
		}

		visualObject->setPosition(this->position);
		visualObject->setRotation(rotation.x, rotation.y, rotation.z);
	
	}
	void PhysicsContactSoundManager::physicsContact(const PhysicsContact &contact)
	{
		// WARNING: unsafe IGamePhysicsObject -> AbstractPhysicsObject casts!
		AbstractPhysicsObject *o1 = (AbstractPhysicsObject *)contact.obj1;
		AbstractPhysicsObject *o2 = (AbstractPhysicsObject *)contact.obj2;
		//assert(o1 != NULL);
		//assert(o2 != NULL);
		assert(contact.physicsObject1);
		assert(contact.physicsObject2);

#ifdef PHYSICS_PHYSX
		int sm1 = contact.physicsObject1->getIntData();
		int sm2 = contact.physicsObject2->getIntData();

		// int claw_material = impl->soundmp->getMaterialIndexByName( "claw" );
		// int claw_body_material = impl->soundmp->getMaterialIndexByName( "claw_body" );

		if(sm1 == SOUNDMATERIALPARSER_NO_SOUND_INDEX || sm2 == SOUNDMATERIALPARSER_NO_SOUND_INDEX)
		{
			return;
		}
#else
		if (o1->getSoundMaterial() == SOUNDMATERIALPARSER_NO_SOUND_INDEX
			|| o2->getSoundMaterial() == SOUNDMATERIALPARSER_NO_SOUND_INDEX)
		{
			return;
		}
#endif

		const util::SoundMaterialParser::SoundMaterialList &smlist = impl->soundmp->getSoundMaterials();
		for (int i = 0; i < 2; i++)
		{
			AbstractPhysicsObject *o = o1;
			if (i == 1) 
			{
				o = o2;
			}
#ifdef PHYSICS_PHYSX
			int smindex = sm1;
			if (i == 1) 
			{
				smindex = sm2;
			}
			assert(smindex >= 0 && smindex < (int)smlist.size());
#else
			int smindex = o->getSoundMaterial();
#endif

			bool makeSound = false;
			VC3 soundpos;

			if(o)
			{
				/*
				// debug logging
				if( contact.contactForceLen > 1.0f && smlist[smindex].sounds.empty() == false )
				{
					VC3 accel = o->getAcceleration();
					VC3 angaccel = o->getAngularAcceleration();

					std::stringstream ss;
					ss << contact.contactForceLen << ", " << accel.GetLength() << ", " << angaccel.GetLength() << std::endl;
					Logger::getInstance()->error( ss.str().c_str() );
				}
				*/

				if(contact.contactForceLen >= smlist[smindex].requiredForce)
				{
					// TODO: use contact position instead of object's position.
					soundpos = o->getPosition();

					VC3 accel = o->getAcceleration();
					VC3 angaccel = o->getAngularAcceleration();

					

					

					if (accel.GetSquareLength() >= smlist[smindex].requiredAcceleration * smlist[smindex].requiredAcceleration
						|| angaccel.GetSquareLength() >= smlist[smindex].requiredAngularAcceleration * smlist[smindex].requiredAngularAcceleration)
					{
						makeSound = true;

						/*
						std::vector<std::string> soundlist = smlist[smindex].sounds;
						if (soundlist.size() > 0)
						{
							// TODO: some better pseudo-random logic here maybe...
							int sndnum = rand() % soundlist.size();
							const char *soundfile = soundlist[sndnum].c_str();

							float volumeFactor = 1.0f;
							if (smlist[smindex].requiredForce > 0.0f)
							{
								// 40% - 100% volume factor (100% required force - 200% required force)
								volumeFactor = (contact.contactForceLen / smlist[smindex].requiredForce) - 1.0f;
								volumeFactor *= 0.6f;
								volumeFactor += 0.4f;
								if (volumeFactor > 1.0f)
									volumeFactor = 1.0f;

								assert(volumeFactor >= 0.4f);
								assert(volumeFactor <= 1.0f);
							}

							impl->gameUI->playSoundEffect(soundfile, soundpos.x, soundpos.y, soundpos.z, 
								false, (int)(DEFAULT_SOUND_EFFECT_VOLUME * volumeFactor), DEFAULT_SOUND_RANGE, DEFAULT_SOUND_PRIORITY_NORMAL);
						}
						*/
					}

				}

				// not to repeat the effect too frequently
				if( o != NULL && makeSound && ( impl->gameUI->game->gameTimer - o->getLastEffectSoundTick() ) > ( 200 / GAME_TICK_MSEC ) )
				{
					o->setLastEffectSoundTick( impl->gameUI->game->gameTimer ); 
				}
				else
				{
					makeSound = false;
				}
			}
			else
			{
				if(contact.contactForceLen >= smlist[smindex].requiredForce)
				{
					makeSound = true;

#ifdef PHYSICS_PHYSX
					if(i == 0)
						contact.physicsObject1->getPosition(soundpos);
					else
						contact.physicsObject2->getPosition(soundpos);
#endif
				}
			}

			if(makeSound)
			{
				std::vector<std::string> soundlist = smlist[smindex].sounds;
				if (soundlist.size() > 0)
				{
					// TODO: some better pseudo-random logic here maybe...
					int sndnum = rand() % soundlist.size();
					// const char *soundfile = soundlist[sndnum].c_str();
					
					float volumeFactor = 1.0f;
					std::string soundfile = soundlist[sndnum];

					if (smlist[smindex].requiredForce > 0.0f)
					{
						// 100% required force - 500% required force
						float contactFactor = contact.contactForceLen / ( smlist[smindex].requiredForce * 5.0f );
						if( contactFactor > 1.0f ) 
							contactFactor = 1.0f;

						int sndnum = (int)((float)( soundlist.size() - 1 ) * contactFactor + 0.5f);
						sndnum += ( rand() % 3 ) - 1;

						if( sndnum < 0 ) 
							sndnum = 0;
						
						if( sndnum > (signed)( soundlist.size() - 1 ) ) 
							sndnum = (signed)( soundlist.size() - 1 );
						
						soundfile = soundlist[sndnum];
						/*
						// 40% - 100% volume factor (100% required force - 200% required force)
						volumeFactor = (contact.contactForceLen / smlist[smindex].requiredForce) - 1.0f;
						volumeFactor *= 0.6f;
						volumeFactor += 0.4f;
						if (volumeFactor > 1.0f)
							volumeFactor = 1.0f;

						assert(volumeFactor >= 0.4f);
						assert(volumeFactor <= 1.0f);
						*/
					}

					impl->gameUI->playSoundEffect(soundfile.c_str(), soundpos.x, soundpos.y, soundpos.z, 
						false, (int)(DEFAULT_SOUND_EFFECT_VOLUME * volumeFactor), DEFAULT_SOUND_RANGE, DEFAULT_SOUND_PRIORITY_NORMAL);
				}
			}
		}
	}
Beispiel #21
0
void Storm3D_SpotlightShared::updateMatricesOffCenter(const D3DXMATRIX &cameraView, const VC2 &min, const VC2 &max, float height, Storm3D_Camera &camera)
{
	// Position of the light in global coordinates
	// Y-axis is height
	D3DXVECTOR3 lightPosition(position.x, position.y, position.z);
	// Up vector (z-axis)
	D3DXVECTOR3 up(0.f, 0.f, 1.f);
	// Look direction
	D3DXVECTOR3 lookAt = lightPosition;
	lookAt.y -= 1.f;

	{
		// max and min define the extents of light area in local coordinates
		// Z-axis is height
		float zmin = 0.2f;
		//float zmax = std::max(range, height) * 1.4f;
		// height is light height from light properties
		float zmax = height;
		float factor = 1.5f * zmin / height;
		float xmin = min.x * factor;
		float xmax = max.x * factor;
		float ymin = min.y * factor;
		float ymax = max.y * factor;
		D3DXMatrixPerspectiveOffCenterLH(&lightProjection, xmin, xmax, ymin, ymax, zmin, zmax);

		// Calculate the extents of light area in global coordinates
		VC2 worldMin = min;
		worldMin.x += position.x;
		worldMin.y += position.z;
		VC2 worldMax = max;
		worldMax.x += position.x;
		worldMax.y += position.z;

		// Generate approximate camera for culling.

		// Calculate range of the camera.
		// Y-axis is height
		float planeY = position.y - height;
		// Calculate distances from light position to light plane edges
		VC3 p1 = VC3( worldMin.x, planeY, worldMin.y ) - position;
		VC3 p2 = VC3( worldMax.x, planeY, worldMin.y ) - position;
		VC3 p3 = VC3( worldMax.x, planeY, worldMax.y ) - position;
		VC3 p4 = VC3( worldMin.x, planeY, worldMax.y ) - position;
		float d1 = p1.GetLength();
		float d2 = p2.GetLength();
		float d3 = p3.GetLength();
		float d4 = p4.GetLength();
		float maxRange = 0.0f;
		maxRange = MAX( maxRange, d1 );
		maxRange = MAX( maxRange, d2 );
		maxRange = MAX( maxRange, d3 );
		maxRange = MAX( maxRange, d4 );
		//maxRange = sqrtf(maxRange);

		// Calculate FOV of the camera.
		VC3 planeCenter = VC3( (worldMin.x + worldMax.x) * 0.5f, planeY, (worldMin.y + worldMax.y) * 0.5f );
		VC3 camVec = planeCenter - position;
		camVec.Normalize();
		float minDot = 10000.0f;
		float t1 = camVec.GetDotWith( p1 ) / d1;
		float t2 = camVec.GetDotWith( p2 ) / d2;
		float t3 = camVec.GetDotWith( p3 ) / d3;
		float t4 = camVec.GetDotWith( p4 ) / d4;
		minDot = MIN( minDot, t1 );
		minDot = MIN( minDot, t2 );
		minDot = MIN( minDot, t3 );
		minDot = MIN( minDot, t4 );
		float maxAngle = acosf( minDot );

		// Place camera to light position
		camera.SetPosition(position);
		camera.SetUpVec(VC3(0.f, 0.f, 1.f));
		// Point camera at light plane center
		camera.SetTarget(planeCenter);
		camera.SetFieldOfView( maxAngle );
		camera.SetVisibilityRange( maxRange );
	}
	
	D3DXMATRIX cameraMatrix(cameraView);
	float det = D3DXMatrixDeterminant(&cameraMatrix);
	D3DXMatrixInverse(&cameraMatrix, &det, &cameraMatrix);

	unsigned int tweakRange = 1;
	float bias = 0.f;
	float currentBias = 0.f;
	for(int i = 0; i < 2; ++i)
	{	
		D3DXMatrixLookAtLH(&lightView[i], &lightPosition, &lookAt, &up);
		if(i == 1)
			currentBias = 0;

		// Tweak matrix
		float soffsetX = 0.5f;
		float soffsetY = 0.5f;
		float scale = 0.5f;

		D3DXMATRIX shadowTweak( scale,    0.0f,     0.0f,				0.0f,
								0.0f,     -scale,   0.0f,				0.0f,
								0.0f,      0.0f,     float(tweakRange),	0.0f,
								soffsetX,  soffsetY, currentBias,		1.0f );

		D3DXMatrixMultiply(&shadowProjection[i], &lightProjection, &shadowTweak);
		D3DXMatrixMultiply(&shadowProjection[i], &lightView[i], &shadowProjection[i]);
		D3DXMatrixMultiply(&lightViewProjection[i], &lightView[i], &lightProjection);

		shaderProjection[i] = shadowProjection[i];
		D3DXMatrixMultiply(&shadowProjection[i], &cameraMatrix, &shadowProjection[i]);
	}

	{
		float xf = (1.f / resolutionX * .5f);
		float yf = (1.f / resolutionY * .5f);
		float sX = soffsetX + (2 * targetPos.x * soffsetX) - xf;
		float sY = soffsetY + (2 * targetPos.y * soffsetY) - yf;

		D3DXMATRIX shadowTweak( scaleX,    0.0f,	0.0f,				0.0f,
								0.0f,    -scaleY,	0.0f,				0.0f,
								0.0f,     0.0f,     float(tweakRange),	0.0f,
								sX,       sY,		bias,				1.0f );

		D3DXMatrixMultiply(&targetProjection, &lightProjection, &shadowTweak);
		D3DXMatrixMultiply(&targetProjection, &lightView[0], &targetProjection);
	}
}
		void run(const VC3 &playerPosition)
		{
			// not enabled? then return
			if (!this->enabled)
				return;

			// still some manual delay set until next spawn? then return
			if (this->nextSpawnDelay > 0)
			{
				this->nextSpawnDelay--;
				return;
			}

			this->currentTime++;

			// is this a spawn interval tick? if not, then return
			if ((this->currentTime % this->spawnInterval) != 0)
				return;


			float closestDistSq = ALIENSPAWNER_MAX_SPAWN_RANGE * ALIENSPAWNER_MAX_SPAWN_RANGE;
			int closestId = -1;

#ifdef PROJECT_SURVIVOR
			
			// get random spawn point
			int temp_count = 0;
			int max_random = ALIENSPAWNER_MAX_SPAWNPOINTS;
			while( temp_count <= ALIENSPAWNER_MAX_SPAWNPOINTS && closestId == -1 )
			{
				temp_count++;
				int i = 0;
				if( i != 0 )
					i = game->gameRandom->nextInt() % max_random;

				if( spawnPoint[i].spawnerScriptId != 0 )
				{
					if( scriptEnabled[spawnPoint[i].spawnerScriptId] )
					{
						closestId = i;
					}
				}
				else
				{
					if( i < max_random )
						max_random = i;
				}
			}					
#else
			// TODO: more efficient datastructure
			for (int i = 0; i < ALIENSPAWNER_MAX_SPAWNPOINTS; i++)
			{
				if (spawnPoint[i].spawnerScriptId != 0)
				{
					if (scriptEnabled[spawnPoint[i].spawnerScriptId])
					{
						VC3 diffVec = spawnPoint[i].position - playerPosition;
						float distSq = diffVec.GetSquareLength();
						if (distSq < closestDistSq
							&& distSq > ALIENSPAWNER_MIN_SPAWN_RANGE * ALIENSPAWNER_MIN_SPAWN_RANGE)
						{
							closestId = i;
							closestDistSq = distSq;

							float d = sqrtf(closestDistSq) + ALIENSPAWNER_SPAWN_RANGE_RAND * float(game->gameRandom->nextInt() % 101) / 100.0f;
							closestDistSq = d * d;
						}
					}
				} else {
					break;
				}
			}
#endif
			if (closestId != -1)
			{
				game->gameScripting->runOtherScript(spawnerScripts[spawnPoint[closestId].spawnerScriptId].c_str(), "spawn", NULL, spawnPoint[closestId].position);
			}

		}
Beispiel #23
0
void ClawUnitActor::actDirectClawControls(Unit *unit)
{
	int weapTypeNum = 0;
	static int rotating = 0;
  static bool claw_near = true;

	UnitType *unitType = unit->getUnitType();

	if (rotating) rotating--;

	// For longer claw -> 5.5, 5.0

	const game::ControlSettings &controlSettings = game->getClawController()->getControlSettings();
	if(game->getClawController()->hasActor())
	{
		if(game->getClawController()->getTargetPosition(TARGET_ADVANCE_TICKS).GetRangeTo(unit->getPosition()) > controlSettings.animationSwitchFarPoseRange) 
		 claw_near = false;
    if(game->getClawController()->getTargetPosition(TARGET_ADVANCE_TICKS).GetRangeTo(unit->getPosition()) < controlSettings.animationSwitchNearPoseRange && !rotating) 
		 claw_near = true;
	}
	else
	{
    if(game->getClawController()->getTargetPosition(TARGET_ADVANCE_TICKS).GetRangeTo(unit->getPosition()) > controlSettings.animationSwitchFarPoseRange) 
		 claw_near = false;
    if(game->getClawController()->getTargetPosition(TARGET_ADVANCE_TICKS).GetRangeTo(unit->getPosition()) < controlSettings.animationSwitchNearPoseRange && !rotating) 
		 claw_near = true;
	}

	//bool sprint_key = game->gameUI->isLocalPlayerDirectControlOn(DIRECT_CTRL_SPRINT, unit);

	bool sprint = false;
	// TODO: ask the clawcontroller if we should sprint - if claw (= pad aiming/mouse) is not moving?
	// if sprint key is pressed, then force the claw not to move

static int thefoocounter = 0;

	if (!game->getClawController()->hasActor()
		&& !game->getClawController()->isClawMoving())
	{
		thefoocounter++;
		if (thefoocounter > 67)
		{
			sprint = true;
		}
	} else {
		thefoocounter = 0;
	}

// SPRINT DISABLED FOR NOW!
sprint = false;

	if (game->getClawController()->getPrepareAction() != ClawController::ActionNone)
	{
		weapTypeNum = 6;
	} else
	{
		if(sprint)
		{
			weapTypeNum = 5;
		} else {
			if(!claw_near)
			{
				if(game->getClawController()->hasActor())
				{
					weapTypeNum = 4;
				}
				else
				{
					weapTypeNum = 2;
				}
			}
			else
			{
				if(game->getClawController()->hasActor())
				{
					weapTypeNum = 3;
				}
				else
				{
					weapTypeNum = 1;
				}
			}
		}
	}

	bool weaponAnimationTypeChanged = false;

	// HACK: hack hack hack static!
	static int lastWeapTypeNum = -1;
	static int weaponChanging = 0;
	if (weapTypeNum != lastWeapTypeNum)
	{
		lastWeapTypeNum = weapTypeNum;
		weaponAnimationTypeChanged = true;
		weaponChanging = GAME_TICKS_PER_SECOND;
	}
  if (weaponChanging) weaponChanging--;
	int anim = ANIM_STAND_TYPE0 + weapTypeNum;

	// get the controls...
	bool up = game->gameUI->isLocalPlayerDirectControlOn(DIRECT_CTRL_FORWARD, unit);
	bool left = game->gameUI->isLocalPlayerDirectControlOn(DIRECT_CTRL_LEFT, unit);
	bool right = game->gameUI->isLocalPlayerDirectControlOn(DIRECT_CTRL_RIGHT, unit);
	bool down = game->gameUI->isLocalPlayerDirectControlOn(DIRECT_CTRL_BACKWARD, unit);

	// initial control coord system (controls in camera coord sys)
	VC3 upvec = VC3(0,1,0);
	VC3 controlFrontVec = VC3(0,0,-1);
	VC3 controlSideVec = controlFrontVec.GetCrossWith(upvec);

	// HACK: hack hack hack static!
	// (if we haven't moved, this is the last moved direction)
	static VC3 controlDirVec = VC3(1,0,0);
	bool doMovement = false;

	if (up || down || left || right)
	{
		VC3 newControlDirVec = VC3(0,0,0);
		if(!game::SimpleOptions::getBool(DH_OPT_B_CLAW_MOUSE))
		{
			int jx = 0;
			int jy = 0;
			Keyb3_ReadJoystick(0, &jx, &jy, 0, 0, 0, 0);
			//if(abs(jx) < 4)
			//	jx = 0;
			//if(abs(jy) < 4)
			//	jy = 0;

			newControlDirVec -= controlSideVec * float(jx);
			newControlDirVec -= controlFrontVec * float(jy);
		}
		else
		{
			if (up)
				newControlDirVec += controlFrontVec;
			if (down)
				newControlDirVec -= controlFrontVec;
			if (left)
				newControlDirVec += controlSideVec;
			if (right)
				newControlDirVec -= controlSideVec;
		}

		if (newControlDirVec.x != 0 || newControlDirVec.y != 0 || newControlDirVec.z != 0)
		{
			newControlDirVec.Normalize();
			controlDirVec = newControlDirVec;
			doMovement = true;
		}
	}

	// camera front/side vectors (height is flattened off)
	VC3 cameraFrontVec = game->gameUI->getGameCamera()->getTargetPosition() - game->gameUI->getGameCamera()->getPosition();
	cameraFrontVec.y = 0.0f;
	if (cameraFrontVec.GetSquareLength() < 0.0001f)
	{
		cameraFrontVec = controlFrontVec;
	}
	cameraFrontVec.Normalize();
	VC3 cameraSideVec = cameraFrontVec.GetCrossWith(upvec);

	// translate movement direction from camera coord system to global ocoord. system	
	// this is the actual movement direction vector.
	VC3 globalDirVec = (cameraFrontVec * controlDirVec.GetDotWith(controlFrontVec)) + (cameraSideVec * controlDirVec.GetDotWith(controlSideVec));

	VC3 velocity = unit->getVelocity();

	// move
	if (doMovement)
	{
		float accel = unitType->getAcceleration() / GAME_TICKS_PER_SECOND;
		velocity += globalDirVec * accel;

		float maxspeed = unitType->getMaxSpeed() / GAME_TICKS_PER_SECOND;
		if (sprint)
		{
			maxspeed = unitType->getSprintSpeed() / GAME_TICKS_PER_SECOND;
		}
		if (weapTypeNum == 6)  maxspeed = unitType->getSlowSpeed() / GAME_TICKS_PER_SECOND;
		float velTotalSq = velocity.GetSquareLength();
		if (velTotalSq > maxspeed*maxspeed)
		{
			velocity *= maxspeed / (float)sqrtf(velTotalSq);
		}

	}

	// friction...
	frictionVelocity(&velocity, unitType->getFriction() * GAME_TICK_MSEC);

	unit->setVelocity(velocity);

	// where do we move to?
	float moveAngle = util::PositionDirectionCalculator::calculateDirection(VC3(0,0,0), globalDirVec);
	float rotateToAngle = moveAngle;



	bool doStrafeLeftAnim = false;
	bool doStrafeRightAnim = false;
	bool doStrafeBackAnim = false;

	static float standAngle = 0;
	
	// where do we aim?
	float aimDestAngle = moveAngle;
	char *aimBone = unitType->getAimBone();
	if (aimBone != NULL)
	{
		VC3 unitPos = unit->getPosition();

		
/*		static VC3 aimPos = VC3(0,0,0);
		VC3 aimDiff = game->getClawController()->getClawPosition() - unitPos;
		if (aimDiff.GetSquareLength() > 2.0f * 2.0f)
		{
			aimPos = game->getClawController()->getClawPosition();
		}*/
		
//		VC3 aimPos = game->getClawController()->getClawPosition();
		VC3 aimPos = game->getClawController()->getTargetPosition(TARGET_ADVANCE_TICKS);

		aimDestAngle = util::PositionDirectionCalculator::calculateDirection(unitPos, aimPos);

		if (doMovement)
		{
			// --- THE HORRIBLE STRAFE LOGIC BEGINS ---
			float insideFwd = util::AngleRotationCalculator::getRotationForAngles(moveAngle, aimDestAngle, 45.0f);
			if (insideFwd == 0)
			{
				rotateToAngle = moveAngle;
			} else {
				float insideFwdDiag = util::AngleRotationCalculator::getRotationForAngles(moveAngle, aimDestAngle, 90.0f+45.0f);
				if (insideFwdDiag == 0)
				{
					if (insideFwd < 0)
					{
						rotateToAngle = moveAngle - 90.0f;
						if (rotateToAngle < 0.0f) rotateToAngle += 360.0f;
						doStrafeRightAnim = true;
					} else {
						rotateToAngle = moveAngle + 90.0f;
						if (rotateToAngle >= 360.0f) rotateToAngle -= 360.0f;
						doStrafeLeftAnim = true;
					}
				} else {
					rotateToAngle = moveAngle + 180.0f;
					if (rotateToAngle >= 360.0f) rotateToAngle -= 360.0f;
					doStrafeBackAnim = true;
				}
			}
			// --- THE HORRIBLE STRAFE LOGIC ENDS ---

		} else {
			if (weaponAnimationTypeChanged)
			{
				standAngle = aimDestAngle;
			}
			rotateToAngle = standAngle;

			// HACK: ...
			float maxTwist = 45.0f;
			if (weapTypeNum == 6)
			{
				maxTwist = 10.0f;
			}

			while (true)
			{
				float tooFarTwist = util::AngleRotationCalculator::getRotationForAngles(rotateToAngle, aimDestAngle, maxTwist+10);
				if (tooFarTwist > 0)
				{
					rotateToAngle += maxTwist*2;
					if (rotateToAngle >= 360.0f) rotateToAngle -= 360.0f;
				}
				else if (tooFarTwist < 0)
				{
					rotateToAngle -= maxTwist*2;
					if (rotateToAngle < 0.0f) rotateToAngle += 360.0f;
				} else {
					break;
				}
			}
		}
	}

	// When aiming, force rotation to dest.
	if (weapTypeNum == 6)
	{
		rotateToAngle = util::PositionDirectionCalculator::calculateDirection(
			unit->getPosition(),
			game->getClawController()->getTargetPosition(0));
	}

	if (doMovement)
	{
		standAngle = moveAngle;
		weaponChanging = GAME_TICKS_PER_SECOND / 4;
	}

	// rotate towards movement/strafe/whatever we just decided
	VC3 rot = unit->getRotation();

	float turnAccuracy = unitType->getTurningAccuracy();
	float turnSpeed = unitType->getTurning();
  // HACK, if unit is walking, slow it's turning speed down
	if (doMovement) {
		turnSpeed *= 0.7f;
	}

	float turnDir = util::AngleRotationCalculator::getRotationForAngles(rot.y, rotateToAngle, turnAccuracy);
//Logger::getInstance()->error(int2str((int)turnDir));
	rot.y += turnSpeed / GAME_TICKS_PER_SECOND * turnDir;
//	Logger::getInstance()->warning(int2str(rot.y));
//	Logger::getInstance()->warning(int2str(aimDestAngle));
	if (rotateToAngle - rot.y < -180) rotateToAngle +=360;
	if (rotateToAngle - rot.y > 180) rotateToAngle -=360;
	if (turnDir > 0 && rot.y > rotateToAngle)
	{
		rot.y = rotateToAngle;
	}
	if (turnDir < 0 && rot.y < rotateToAngle)
	{
		rot.y = rotateToAngle;
	}
	if (rot.y >= 360.0f) rot.y -= 360.0f;
	if (rot.y < 0.0f) rot.y += 360.0f;

	unit->setRotation(rot.x, rot.y, rot.z);

	// aim towards final aim direction...
	if (aimBone != NULL)
	{
		float aimAngle = aimDestAngle - rot.y;
		if (aimAngle < 0) aimAngle += 360.0f;

		unit->setLastBoneAimDirection(aimAngle);
		if (unit->getVisualObject() != NULL)
		{
			unit->getVisualObject()->rotateBone(aimBone, aimAngle, 0);
		}
	}

	// TODO: select correct animation
	if (doMovement)
	{
		if (doStrafeLeftAnim)
		{
			anim = ANIM_STRAFE_LEFT_TYPE0 + weapTypeNum;
		}
		else if (doStrafeRightAnim)
		{
			anim = ANIM_STRAFE_RIGHT_TYPE0 + weapTypeNum;
		}
		else if (doStrafeBackAnim)
		{
			anim = ANIM_RUN_BACKWARD_TYPE0 + weapTypeNum;
		} else {
			anim = ANIM_RUN_TYPE0 + weapTypeNum;
		}
	} else if (!weaponChanging) {

		// HACK: ... total hack!
		bool nappi = game->gameUI->getController(0)->isKeyDown(DH_CTRL_ATTACK_SECONDARY);

		if (turnDir < 0)
		{
			if (nappi && weapTypeNum == 4)
			{
				anim = ANIM_SPECIAL2;
			} else {
				anim = ANIM_TURN_LEFT_TYPE0 + weapTypeNum;
			}
			rotating = int(0.5*GAME_TICKS_PER_SECOND);
		}
		if (turnDir > 0)
		{
			if (nappi && weapTypeNum == 4)
			{
				anim = ANIM_SPECIAL1;
			} else {
				anim = ANIM_TURN_RIGHT_TYPE0 + weapTypeNum;
			}
			rotating = int(0.5*GAME_TICKS_PER_SECOND);
		}
	}

//Logger::getInstance()->error(int2str(anim));
	// apply the animation...
	if (unit->getAnimationSet() != NULL)
	{
		if (unit->getAnimationSet()->isAnimationInSet(anim))
		{
			unit->getAnimationSet()->animate(unit, anim);
			if (unit->getAnimationSet()->isAnimationStaticFactored(anim))
			{
				float fact = unit->getAnimationSet()->getAnimationStaticFactor(anim);
				ui::Animator::setAnimationSpeedFactor(unit, fact);
			} else {
				ui::Animator::setAnimationSpeedFactor(unit, 1.0f);
			}
		}	else {
			Logger::getInstance()->warning("ClawUnitActor::actDirectClawControls - Requested anim not found in animation set.");
			Logger::getInstance()->debug("anim id number follows:");
			Logger::getInstance()->debug(int2str(anim));
		}
	} else {
		Logger::getInstance()->warning("ClawUnitActor::actDirectClawControls - Unit has null animation set.");
	}
}
Beispiel #24
0
	void DevScripting::process(util::ScriptProcess *sp, 
		int command, int intData, char *stringData, ScriptLastValueType *lastValue, 
		GameScriptData *gsd, Game *game, bool *pause)
	{
		switch(command)
		{
		case GS_CMD_ERROR:
			//sp->error("DevScripting::process - Script error:");
			Logger::getInstance()->error("DevScripting::process - Script error:");
			if (stringData != NULL)
			{
				sp->error(stringData);
			} else {
				sp->error("DevScripting::process - Script error (error command has null parameter).");
			}
			break;

		case GS_CMD_RELOADSCRIPTFILE:
			if (stringData != NULL)
			{
				util::ScriptManager::getInstance()->loadScripts(stringData, NULL, true);
			} else {
				sp->error("GameScripting::process - reloadScriptFile parameter missing.");
			}
			break;

		case GS_CMD_reloadParticleEffects:
			if (game->inCombat
				&& game->gameUI->getVisualEffectManager() != NULL)
			{
				game->gameUI->getVisualEffectManager()->loadParticleEffects();
				Logger::getInstance()->info("GameScripting::process - reloadParticleEffects, particle effects reloaded (existing effects may not be affected).");
			} else {
				sp->warning("GameScripting::process - reloadParticleEffects called while in menus or no visual effect manager loaded (call ignored).");
			}
			break;

		case GS_CMD_RELOADSTRINGVALUESCRIPTFILE:
			if (gsd->stringValue != NULL)
			{
				util::ScriptManager::getInstance()->loadScripts(gsd->stringValue, NULL, true);
			} else {
				sp->error("GameScripting::process - reloadStringValueScriptFile for null string.");
			}
			break;

		case GS_CMD_SCRIPTDUMP:
			{
				Logger::getInstance()->debug("Script dump command encountered, output follows...");
				char *dump = sp->getScript()->getDebugDump(sp, false);
				if (dump != NULL)
				{
					Logger::getInstance()->debug(dump);
					delete [] dump;
				} else {
					Logger::getInstance()->debug("Null output."); 				
					assert(0);
				}
			}
			break;

		case GS_CMD_FULLSCRIPTDUMP:
			{
				Logger::getInstance()->debug("Full script dump command encountered, output follows...");
				char *dump = sp->getScript()->getDebugDump(sp, true);
				if (dump != NULL)
				{
					Logger::getInstance()->debug(dump);
					delete [] dump;
				} else {
					Logger::getInstance()->debug("Null output."); 				
					assert(0);
				}
			}
			break;


		case GS_CMD_DEVUNITSCRIPTDUMP:
			{
				Logger::getInstance()->debug("Dev unit script dump command encountered, output follows...");
					// WARNING: unsafe cast!
				util::ScriptProcess *mainsp = ((game::UnitLevelAI *)game->devUnit->getAI())->mainScriptProcess;
				char *dump = mainsp->getScript()->getDebugDump(mainsp, false);
				if (dump != NULL)
				{
					Logger::getInstance()->debug(dump);
					delete [] dump;
				} else {
					Logger::getInstance()->debug("Null output."); 				
					assert(0);
				}
			}
			break;

		case GS_CMD_DEVUNITFULLSCRIPTDUMP:
			{
				if (game->devUnit != NULL)
				{
					Logger::getInstance()->debug("Dev unit full script dump command encountered, output follows...");
					// WARNING: unsafe cast!
					util::ScriptProcess *mainsp = ((game::UnitLevelAI *)game->devUnit->getAI())->mainScriptProcess;
					char *dump = mainsp->getScript()->getDebugDump(mainsp, true);
					if (dump != NULL)
					{
						Logger::getInstance()->debug(dump);
						delete [] dump;
					} else {
						Logger::getInstance()->debug("Null output."); 				
						assert(0);
					}
				}
			}
			break;

		case GS_CMD_DEVMESSAGE:
			if (stringData != NULL)
			{
				if (SimpleOptions::getBool(DH_OPT_B_SCRIPT_DEV_MODE))
				{
					if (game->devUnit == NULL 
						|| gsd->unit == game->devUnit)
					{
						sp->warning(stringData);
					}
				}
			}
			break;

		case GS_CMD_HIDECONSOLE:
			game->gameUI->hideConsole();
			break;

		case GS_CMD_SHOWCONSOLE:
			game->gameUI->showConsole();
			break;

		case GS_CMD_DEVSIDESWAP:
			if (intData >= 0 && intData < ABS_MAX_PLAYERS)
			{
				if (SimpleOptions::getBool(DH_OPT_B_ALLOW_SIDE_SWAP)
					&& game->inCombat)
				{
					sp->debug("DevScripting::process - Swapping sides.");

					game->unitSelections[game->singlePlayerNumber]->selectAllUnits(false);
					
					game->gameUI->closeCombatWindow(game->singlePlayerNumber);
					game->singlePlayerNumber = intData;
					game->gameUI->openCombatWindow(game->singlePlayerNumber);
				}
			} else {
				sp->warning("DevScripting::process - devSideSwap parameter bad.");
			}
			break;

		case GS_CMD_DEVSIDESWAPTOVALUE:
			if (*lastValue >= 0 && *lastValue < ABS_MAX_PLAYERS)
			{
				if (SimpleOptions::getBool(DH_OPT_B_ALLOW_SIDE_SWAP)
					&& game->inCombat)
				{
					sp->debug("DevScripting::process - Swapping sides.");
					
					game->gameUI->closeCombatWindow(game->singlePlayerNumber);
					game->singlePlayerNumber = *lastValue;
					game->gameUI->openCombatWindow(game->singlePlayerNumber);
				}
			} else {
				sp->warning("DevScripting::process - devSideSwapToValue last value out of ranged.");
			}
			break;

		case GS_CMD_DEVUNIT:
			if (gsd->unit == NULL)
			{
				sp->warning("DevScripting::process - devUnit for null unit.");
				game->devUnit = NULL;
			} else {
				game->devUnit = gsd->unit;	
			}
			break;

		case GS_CMD_CLEARDEVUNIT:
			game->devUnit = NULL;
			break;

		case GS_CMD_DUMPSTATUSINFO:
			if (game->getGameScene() != NULL && game->inCombat)
			{
				char *stats = game->getGameScene()->getStorm3D()->GetPrintableStatusInfo();
				Logger::getInstance()->info(stats);
				game->getGameScene()->getStorm3D()->DeletePrintableStatusInfo(stats);
				
				Logger::getInstance()->info("Visual effects running:");
				Logger::getInstance()->info(int2str(ui::visual_effect_allocations));
			} else {
				Logger::getInstance()->warning("DevScripting::process - dumpStatusInfo cannot get info for null scene.");
			}
			break;

		case GS_CMD_dumpEffectsInfo:
			if (game->getGameScene() != NULL && game->inCombat)
			{
				Logger::getInstance()->info("Visual effects running:");
				Logger::getInstance()->info(int2str(ui::visual_effect_allocations));
				Logger::getInstance()->info("Particle spawners total amount:");
				Logger::getInstance()->info(int2str(game->particleSpawnerManager->getParticleSpawnerAmount()));
			} else {
				Logger::getInstance()->warning("DevScripting::process - dumpEffectsInfo cannot get info for null scene.");
			}
			break;

		case GS_CMD_dumpGameSceneGraph:
			{
				char *stats = game->getGameSceneGraphDump();
				Logger::getInstance()->info(stats);
				game->deleteGameSceneGraphDump(stats);
			}
			break;

		case GS_CMD_dumpPhysicsInfo:
			{
				char *stats = UnitPhysicsUpdater::getStatusInfo();
				Logger::getInstance()->info(stats);
				UnitPhysicsUpdater::deleteStatusInfo(stats);
#ifdef PHYSICS_ODE
				stats = PhysicsActorOde::getStatusInfo();
				Logger::getInstance()->info(stats);
				PhysicsActorOde::deleteStatusInfo(stats);
#endif
#ifdef PHYSICS_PHYSX
				if(game->getGamePhysics() && game->getGamePhysics()->getPhysicsLib())
				{
					std::string info = game->getGamePhysics()->getPhysicsLib()->getStatistics();
					Logger::getInstance()->info(info.c_str());
				}
#endif
			}
			break;

		case GS_CMD_RAYTRACEBLAST:
			if (game->getGameScene() != NULL && game->inCombat)
			{
				if (game->gameUI->getFirstPerson(0) != 0)
				{
					if (game->gameUI->getFirstPerson(0)->getVisualObject() != NULL)
					{
						game->gameUI->getFirstPerson(0)->getVisualObject()->setCollidable(false);
					}
					VC3 pos = game->gameUI->getFirstPerson(0)->getPosition();
					pos.y += 1.0f;
					for (float b = -2.0f; b < 1.0f; b += 0.5f)
					{
						for (float a = 0; a < 2*3.1415f; a += 0.25f)
						{
							VC3 dir = VC3(cosf(a), sinf(b / 2.0f), sinf(a));
							dir.Normalize();
							GameCollisionInfo cinfo;
							game->getGameScene()->rayTrace(pos, dir, 20, cinfo, true, false);
						}
					}
					if (game->gameUI->getFirstPerson(0)->getVisualObject() != NULL)
					{
						game->gameUI->getFirstPerson(0)->getVisualObject()->setCollidable(true);
					}
				}
			}
			break;

		case GS_CMD_DEVEXIT:
			sp->error("DevScripting::process - devExit called, making an immediate and unclean exit.");
			exit(0);
			break;

		case GS_CMD_DEVASSERT:
			if (*lastValue == 0)
			{
				sp->warning("DevScripting::process - devAssert.");
				FB_ASSERT(!"DevScripting::process - devAssert.");
			}
			break;

		case GS_CMD_DEVCRASH:
			{
#ifndef FB_TESTBUILD
				sp->warning("DevScripting::process - devCrash ignored.");
#else
				sp->warning("DevScripting::process - devCrash about to crash.");
				FB_ASSERT(!"DevScripting::process - devCrash.");
				int *crashPtr = NULL;
				int crashValue = *crashPtr;
				*lastValue = crashValue;
#endif
			}
			break;

		case GS_CMD_LISTGLOBALVARIABLES:
			{
				LinkedList *tmp = util::Script::getGlobalVariableList(false);

				while (!tmp->isEmpty())
				{
					const char *varname = (const char *)tmp->popLast();
					int varval = 0;
					util::Script::getGlobalIntVariableValue(varname, &varval);

					char *tmpbuf = new char[strlen(varname) + 32];
					strcpy(tmpbuf, varname);
					strcat(tmpbuf, " (");
					strcat(tmpbuf, int2str(varval));
					strcat(tmpbuf, ")");
					Logger::getInstance()->info(tmpbuf);
				}

				delete tmp;
			}
			break;

		case GS_CMD_reloadObjectDurabilities:
			if (gameui_physicsDamageManager != NULL)
			{
				gameui_physicsDamageManager->reloadConfiguration();
			}
			break;

		case GS_CMD_openScoreWindow:
			{
				if( game && game->gameUI )
				{
					game->gameUI->openScoreWindow( game->singlePlayerNumber );
				}
			}
			break;      
      
		case GS_CMD_openMissionSelectionWindow:
			{
				if( game && game->gameUI )
				{
					game->gameUI->openMissionSelectionWindow();
				}
			}
			break;

		case GS_CMD_dumpScriptInfo:
			Logger::getInstance()->info(util::ScriptManager::getInstance()->getStatusInfo().c_str());
			Logger::getInstance()->info("Custom script processes amount:");
			Logger::getInstance()->info(int2str(game->getCustomScriptProcessAmount()));
			break;

		case GS_CMD_devStopAllCustomScripts:
			game->stopAllCustomScriptProcesses();
			break;


#ifndef PROJECT_SHADOWGROUNDS
		case GS_CMD_missionSelectionWindowAddMissionButton:
			{
				if( game && game->gameUI && game->gameUI->getMissionSelectionWindow() )
				{
					game->gameUI->getMissionSelectionWindow()->AddMissionButton( stringData );
				}
			}
			break;
#endif

		case GS_CMD_openMainMenuWindow:
			{
				if( game && game->gameUI )
				{
					game->gameUI->openMainmenuFromGame( intData );
					// game->gameUI->getCommandWindow( game->singlePlayerNumber )->openMenu( intData );
				}
			}
			break;

		case GS_CMD_devRunSingleCommand:
			if (stringData != NULL)
			{				
				int slen = strlen(stringData);
				char *cmdName = new char[slen + 1];
				char *param = new char[slen + 1];
				int cmdNamePos = 0;
				int paramPos = 0;
				cmdName[0] = '\0';
				param[0] = '\0';
				bool trimming = true;
				bool readingCmd = false;
				bool skippingSep = false;
				bool readingParam = false;
				for (int i = 0; i < slen; i++)
				{
					if (trimming)
					{
						if (stringData[i] != ' ' && stringData[i] != '\t')
						{
							trimming = false;
							readingCmd = true;
						}
					}
					if (readingCmd)
					{
						if (stringData[i] == ' ' || stringData[i] == '\t')
						{
							readingCmd  = false;
							skippingSep = true;
						} else {
							cmdName[cmdNamePos] = stringData[i];
							cmdNamePos++;
						}
					}
					if (skippingSep)
					{
						if (stringData[i] != ' ' && stringData[i] != '\t')
						{
							skippingSep = false;
							readingParam = true;
						}
					}
					if (readingParam)
					{
						param[paramPos] = stringData[i];
						paramPos++;
					}
				}
				cmdName[cmdNamePos] = '\0';
				param[paramPos] = '\0';
				if (cmdName[0] == '\0')
				{
					sp->error("DevScripting::process - devRunSingleCommand parameter invalid.");
				} else {
					int tmpInt = *lastValue;
					int tmpInt2 = sp->getSecondaryValue();
					bool success;
					if (!readingParam)
					{
						success = game->gameScripting->runSingleSimpleStringCommand(cmdName, NULL, &tmpInt, &tmpInt2); 
					} else {
						success = game->gameScripting->runSingleSimpleStringCommand(cmdName, param, &tmpInt, &tmpInt2); 
					}
					if (!success)
					{
						sp->error("DevScripting::process - devRunSingleCommand failed.");
					}
					*lastValue = tmpInt;
					sp->setSecondaryValue(tmpInt2);
				}
				delete [] param;
				delete [] cmdName;
			} else {
				sp->error("DevScripting::process - devRunSingleCommand parameter missing.");
			}
			break;

		case GS_CMD_forceCursorVisibility:
			{
				game->gameUI->forceCursorVisibility(intData == 0 ? false : true);
			}
			break;

		case GS_CMD_dumpMemoryInfo:
			{
#ifdef FROZENBYTE_DEBUG_MEMORY
				frozenbyte::debug::dumpLeakSnapshot();
				frozenbyte::debug::markLeakSnapshot();					
#endif
			}
			break;

		case GS_CMD_devPhysicsConnectToRemoteDebugger:
#ifndef FINAL_RELEASE_BUILD
			if (stringData != NULL)
			{
				game->getGamePhysics()->getPhysicsLib()->connectToRemoteDebugger(stringData, 5425);
			} else {
				sp->error("DevScripting::process - devPhysicsConnectToRemoteDebugger parameter missing.");
			}
#else
			sp->error("DevScripting::process - devPhysicsConnectToRemoteDebugger not in build.");
#endif
			break;

		case GS_CMD_clearSelectionVisualizationForUnifiedHandle:
			if (VALIDATE_UNIFIED_HANDLE_BITS(gsd->unifiedHandle))
			{
				SelectionVisualizer::clearSelectionForUnifiedHandle(gsd->unifiedHandle);
			} else {
				sp->error("DevScripting::process - clearSelectionVisualizationForUnifiedHandle, unified handle not valid.");
			}
			break;

		case GS_CMD_setSelectionVisualizationForUnifiedHandle:
			if (VALIDATE_UNIFIED_HANDLE_BITS(gsd->unifiedHandle))
			{
				SelectionVisualizer::setSelectionForUnifiedHandle(gsd->unifiedHandle);
			} else {
				sp->error("DevScripting::process - clearSelectionVisualizationForUnifiedHandle, unified handle not valid.");
			}
			break;

		case GS_CMD_reloadChangedScriptFiles:
			{
				int reloaded = util::ScriptManager::getInstance()->reloadChangedScripts();
				if (reloaded > 0)
				{
					std::string tmp = "reloadChangedScriptFiles - Reloaded ";
					tmp += int2str(reloaded);
					tmp += " script(s).";
					Logger::getInstance()->info(tmp.c_str());
				} else {
					Logger::getInstance()->info("reloadChangedScriptFiles - No scripts were reloaded.");
				}
			}
			break;

		case GS_CMD_restartApplicationSoft:
#ifdef PROJECT_AOV
			Logger::getInstance()->info("DevScripting::process - restartApplicationSoft called.");
			game->gameUI->setQuitRequested();
			::app_soft_restart_requested = true;
#else
			Logger::getInstance()->warning("DevScripting::process - restartApplicationSoft not in build.");
#endif
			break;

		case GS_CMD_restartApplicationHard:
#ifdef PROJECT_AOV
			Logger::getInstance()->info("DevScripting::process - restartApplicationHard called.");
			game->gameUI->setQuitRequested();
			::app_hard_restart_requested = true;
#else
			Logger::getInstance()->warning("DevScripting::process - restartApplicationHard not in build.");
#endif
			break;


		default:
			sp->error("DevScripting::process - Unknown command.");
			assert(0);
		}
	}
Beispiel #25
0
void UnitFormation::addMovePoint(std::vector<Unit *> *units, 
	const VC3 &scaledMapPos, Unit::MoveType moveType)
{
	// If some units have waypoints set, they are overriden

	// If all units have same amount of waypoints, just add
	//	-- Check if too far away from each other??
	// Just override all move points (and target?)

	int i;
	VC3 avgPos = VC3(0,0,0);
	for (i = 0; i < (int)units->size(); i++)
	{
		Unit *u = (*units)[i];
		avgPos += u->getPosition();
	}
	avgPos /= (float)units->size();

	// positions already taken by a unit
	// (so that others won't try to go there too)
	std::vector<std::pair<int, int> > pointsTaken;

	bool clickedBlocked = data->gameScene->isBlockedAtScaled(
		scaledMapPos.x, scaledMapPos.z, 0);

	IStorm3D_Model *buildingModel = NULL;
	ConnectionChecker *connectionChecker = NULL;
	if (units->size() > 1 || clickedBlocked)
	{
		int px = data->gameMap->scaledToPathfindX(scaledMapPos.x);
		int py = data->gameMap->scaledToPathfindY(scaledMapPos.z);		
		buildingModel = data->gameScene->getBuildingModelAtPathfind(px, py);

		// HACK:
		// ok, did we click blocked and not inside building (building wall maybe)?
		// now check if there is a building nearby..
		if (clickedBlocked && buildingModel == NULL)
		{
			px+=2;
			buildingModel = data->gameScene->getBuildingModelAtPathfind(px, py);

			px-=4;
			if (buildingModel == NULL && data->gameMap->inPathfindBoundaries(px, py))
			{
				buildingModel = data->gameScene->getBuildingModelAtPathfind(px, py);
			}

			px+=2;
			py+=2;
			if (buildingModel == NULL && data->gameMap->inPathfindBoundaries(px, py))
			{
				buildingModel = data->gameScene->getBuildingModelAtPathfind(px, py);
			}

			py-=4;
			if (buildingModel == NULL && data->gameMap->inPathfindBoundaries(px, py))
			{
				buildingModel = data->gameScene->getBuildingModelAtPathfind(px, py);
			}
		}

		// smaller "rooms" inside buildings...
		int connDist = 14;
		if (buildingModel != NULL) connDist = 10;
		connectionChecker = new ConnectionChecker(data->gameScene, px, py, connDist);
	}

	for (i = 0; i < (int)units->size(); i++)
	{
		Unit *u = (*units)[i];

		UnitActor *ua = getUnitActorForUnit(u);
		
    VC3 offset = u->getPosition() - avgPos;
		offset.y = 0;

		float offsetLen = offset.GetLength();
		if (offsetLen > 0.01f)
		{
			offset.Normalize();
		}

		float destX, okDestX;
		float destZ, okDestZ;

		//okDestX = scaledMapPos.x + offset.x;
		//okDestZ = scaledMapPos.z + offset.z;
		okDestX = scaledMapPos.x;
		okDestZ = scaledMapPos.z;

		float minDist = 0.5f;
		float maxDist = 3.0f;

		if (units->size() == 1) 
		{
			minDist = 0;
			maxDist = 1.0f;
		} else {
			minDist += (float)units->size() * 0.2f;
			maxDist += (float)units->size() * 0.2f;
		}

		bool nonBlockedPassed = false;

		// first solve a position that would kinda match current position
		// in formation... (from formation center to some direction)
		for (float distfactor = minDist; distfactor <= maxDist; distfactor += 0.1f)
		{
			if (distfactor > offsetLen)
				break;

			destX = scaledMapPos.x + (offset.x * distfactor);
			destZ = scaledMapPos.z + (offset.z * distfactor);

			if (data->gameMap->isWellInScaledBoundaries(destX, destZ))
			{
				int ox = data->gameMap->scaledToObstacleX(destX);
				int oy = data->gameMap->scaledToObstacleY(destZ);
				//if (data->gameMap->getObstacleHeight(ox, oy) == 0)
				if (!data->gameScene->isBlocked(ox, oy, 0))
				{
					okDestX = destX;
					okDestZ = destZ;
					nonBlockedPassed = true;
				} else {
					if (nonBlockedPassed)
					{
						break;
					}
				}
			}
		}

		// then try to adjust position so that it would be nicely
		// covered from enemy...
		if (units->size() > 1 || clickedBlocked)
		{			
			int ox = data->gameMap->scaledToObstacleX(okDestX);
			int oy = data->gameMap->scaledToObstacleY(okDestZ);

			/*
			if (connectionChecker != NULL)
			{
				delete connectionChecker;
			}
			connectionChecker = new ConnectionChecker(data->gameScene, ox, oy, 8);
			*/

			VC3 pos = u->getPosition();
			int moveDirX = ox - data->gameMap->scaledToObstacleX(pos.x);
			int moveDirY = oy - data->gameMap->scaledToObstacleY(pos.z);
			int coverFromX = ox + moveDirX;
			int coverFromY = oy + moveDirY;

			if (u->targeting.hasTarget() && u->targeting.getTargetUnit() != NULL)
			{
				VC3 targPos = u->targeting.getTargetUnit()->getPosition();
				coverFromX = data->gameMap->scaledToObstacleX(targPos.x);
				coverFromY = data->gameMap->scaledToObstacleY(targPos.z);
			} else {
				if (u->getSeeUnit() != NULL)
				{
					VC3 seePos = u->getSeeUnit()->getPosition();
					coverFromX = data->gameMap->scaledToObstacleX(seePos.x);
					coverFromY = data->gameMap->scaledToObstacleY(seePos.z);
				}
			}

			int tx1 = ox - 8;
			int ty1 = oy - 8;
			int tx2 = ox + 8;
			int ty2 = oy + 8;
			if (tx1 < 0) tx1 = 0;
			if (ty1 < 0) ty1 = 0;
			if (tx2 >= data->gameMap->getObstacleSizeX()) tx2 = data->gameMap->getObstacleSizeX() - 1;
			if (ty2 >= data->gameMap->getObstacleSizeX()) ty2 = data->gameMap->getObstacleSizeY() - 1;
			int preferX = ox;
			int preferY = oy;
			int preferDistFactorSq = 9999*9999;
			for (int ty = ty1; ty <= ty2; ty++)
			{
				for (int tx = tx1; tx <= tx2; tx++)
				{
					int factSq;
					if (CoverFinder::isCoveredFrom(data->gameMap->getCoverMap(), tx, ty, coverFromX, coverFromY))
					{
						factSq = (tx - ox)*(tx - ox) + (ty - oy)*(ty - oy); 
/*
					}
					else if (data->gameMap->getHideMap()->getHiddenessAt(tx, ty) == HideMap::maxHiddeness)
					{
						// hiddeness not quite as important as covered.
						factSq = 2*(tx - ox)*(tx - ox) + 2*(ty - oy)*(ty - oy);
						factSq += 3*3;
*/
					} else {
					  // no hiddeness, no cover, not preferred very much...
						factSq = 4*(tx - ox)*(tx - ox) + 4*(ty - oy)*(ty - oy);
						factSq += 6*6;
					}

					if (factSq < preferDistFactorSq)
					{
						// penalty for points are already taken by another unit
						int pointAmount = pointsTaken.size();
						for (int i = 0; i < pointAmount; i++)
						{
							if (abs(pointsTaken[i].first - tx) <= 2
								&& abs(pointsTaken[i].second - ty) <= 2)
							{
								if (abs(pointsTaken[i].first - tx) <= 1
									&& abs(pointsTaken[i].second - ty) <= 1)
								{
									if (pointsTaken[i].first == tx
										&& pointsTaken[i].second == ty)
										factSq += 6*6;
									else
										factSq += 4*4;
								} else {
									factSq += 2*2;
								}
							}
						}
					}

					// penalty if not in same building area
					if (factSq < preferDistFactorSq)
					{
						if (data->gameScene->getBuildingModelAtPathfind(tx, ty) != buildingModel)
						{
							factSq += 40*40;
						}
					}

					// penalty if not in the same "room"
					if (factSq < preferDistFactorSq)
					{
						if (!connectionChecker->isCenterConnectedTo(tx - ox, ty - oy))
						{
							factSq += 30*30;
						}
					}

					// blocked really gets penalty :)
					if (data->gameScene->isBlockedAtScaled(
						data->gameMap->obstacleToScaledX(tx), 
						data->gameMap->obstacleToScaledY(ty), 0))
					{
						factSq += 100*100;
					}

					if (factSq < preferDistFactorSq)
					{
						preferDistFactorSq = factSq;
						preferX = tx;
						preferY = ty;
					}
				}
			}
			okDestX = data->gameMap->obstacleToScaledX(preferX);
			okDestZ = data->gameMap->obstacleToScaledY(preferY);

			pointsTaken.push_back(std::pair<int, int>(preferX, preferY));
		}

		// now move right next to any obstacle...
		for (int i = 1; i < 10; i++)
		{
			// right?
			{
				float adjustedX = okDestX + ((float)i / 10.0f);
				float adjustedZ = okDestZ;
				int ox = data->gameMap->scaledToObstacleX(adjustedX);
				int oy = data->gameMap->scaledToObstacleY(adjustedZ);
				//if (data->gameMap->getObstacleHeight(ox, oy) != 0)
				if (data->gameScene->isBlocked(ox, oy, 0))
				{
					okDestX = adjustedX - 0.10f;
					break;
				}
			}
			// left?
			{
				float adjustedX = okDestX - ((float)i / 10.0f);
				float adjustedZ = okDestZ;
				int ox = data->gameMap->scaledToObstacleX(adjustedX);
				int oy = data->gameMap->scaledToObstacleY(adjustedZ);
				//if (data->gameMap->getObstacleHeight(ox, oy) != 0)
				if (data->gameScene->isBlocked(ox, oy, 0))
				{
					okDestX = adjustedX + 0.10f;
					break;
				}
			}
			// up?
			{
				float adjustedX = okDestX;
				float adjustedZ = okDestZ - ((float)i / 10.0f);
				int ox = data->gameMap->scaledToObstacleX(adjustedX);
				int oy = data->gameMap->scaledToObstacleY(adjustedZ);
				//if (data->gameMap->getObstacleHeight(ox, oy) != 0)
				if (data->gameScene->isBlocked(ox, oy, 0))
				{
					okDestZ = adjustedZ + 0.10f;
					break;
				}
			}
			// down?
			{
				float adjustedX = okDestX;
				float adjustedZ = okDestZ + ((float)i / 10.0f);
				int ox = data->gameMap->scaledToObstacleX(adjustedX);
				int oy = data->gameMap->scaledToObstacleY(adjustedZ);
				//if (data->gameMap->getObstacleHeight(ox, oy) != 0)
				if (data->gameScene->isBlocked(ox, oy, 0))
				{
					okDestZ = adjustedZ - 0.10f;
					break;
				}
			}
		}

		// now go to destination...		
		ua->setPathTo(u, VC3(okDestX, 0, okDestZ));

		
		// and set unit behaviour modes...
		if (moveType == Unit::MoveTypeNormal)
		{
			u->setStealthing(false);
			u->setSpeed(Unit::UNIT_SPEED_FAST);
			u->setMode(Unit::UNIT_MODE_DEFENSIVE);
		}
		if (moveType == Unit::MoveTypeFast)
		{
			u->setStealthing(false);
			if (u->getRunningValue() > 0)
			{
				u->setSpeed(Unit::UNIT_SPEED_SPRINT);
				u->setMode(Unit::UNIT_MODE_HOLD_FIRE);
			} else {
				// unit incapable of sprinting, just move at normal running speed.
				u->setSpeed(Unit::UNIT_SPEED_FAST);
				u->setMode(Unit::UNIT_MODE_HOLD_FIRE);
			}
		}
		if (moveType == Unit::MoveTypeStealth)
		{
			// stealth armor goes to stealth mode...
			if (u->getStealthValue() > 0)
			{
				u->setSpeed(Unit::UNIT_SPEED_FAST);
				u->setStealthing(true);
				u->setMode(Unit::UNIT_MODE_HOLD_FIRE);
			} else {
				// other just normal movement (no more sneak)
				//u->setSpeed(Unit::UNIT_SPEED_SLOW);
				u->setSpeed(Unit::UNIT_SPEED_FAST);
				u->setStealthing(false);
				u->setMode(Unit::UNIT_MODE_DEFENSIVE);
			}
		}
	}

	if (connectionChecker != NULL)
	{
		delete connectionChecker;
	}
}
	// return true if position ok and decal should be added
	//        false, if position NOT ok and decal should NOT be added
	bool DecalPositionCalculator::calculateDecalPosition(
		game::GameScene *gameScene,
		const VC3 &origin, const VC3 &velocity, 
		DECAL_POSITIONING positioning, int positionRandom,
		VC3 *resultPosition, QUAT *resultRotation)
	{
		assert(positioning != DecalPositionCalculator::DECAL_POSITIONING_INVALID);

		game::GameMap *gameMap = gameScene->getGameMap();

		bool hitWall = false;

		*resultPosition = origin;
		*resultRotation = QUAT((-3.1415926f / 2.0f),0,0);

		// if velocity positioning...
		if (positioning == DecalPositionCalculator::DECAL_POSITIONING_VELOCITY)
		{
			VC3 velocityRandomized;
			if (positionRandom > 0)
			{
				velocityRandomized = velocity * GAME_TICKS_PER_SECOND;

	// TEMP
	//char buf[64];
	//sprintf(buf, "%f,%f,%f", velocity.x, velocity.y, velocity.z);
	//Logger::getInstance()->error(buf);

				// TODO: add positionRandom to velocity _angle_...
				// (or maybe just do a quick hack and add it to xz-coordinates?)
				velocityRandomized.x += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				velocityRandomized.z += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				
				// add to y too? maybe should add downward only? 
				// NOTE: biased downward
				velocityRandomized.y += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				velocityRandomized.y -= float(positionRandom) / 100.0f * 0.5f;

			} else {
				velocityRandomized = velocity;
			}

			velocityRandomized *= 2.0f;

			IStorm3D_Scene *scene = gameScene->getStormScene();

			VC3 dir = velocityRandomized.GetNormalized();			
			VC3 rayOrigin = origin;
			float rayLen = velocityRandomized.GetLength();

			Storm3D_CollisionInfo sceneColl;
			sceneColl.includeTerrainObjects = false;
			scene->RayTrace(rayOrigin, dir, rayLen, sceneColl, true);

			/*
			if (sceneColl.hit)
			{
				VC3 hitNormal = sceneColl.plane_normal;
				// make a "wall" hit if normal-y is not nearly 1
				//if (fabs(hitNormal.y) < 0.8f)
				{
					hitWall = true;

					VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f);
					x.Normalize();
					x -= hitNormal * x.GetDotWith(hitNormal);
					VC3 y = -x.GetCrossWith(hitNormal);

					assert(fabsf(x.GetDotWith(y)) < 0.0001f);
					assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f);

					MAT tm;
					tm.Set(0, x.x);
					tm.Set(1, x.y);
					tm.Set(2, x.z);
					tm.Set(4, y.x);
					tm.Set(5, y.y);
					tm.Set(6, y.z);
					tm.Set(8, hitNormal.x);
					tm.Set(9, hitNormal.y);
					tm.Set(10, hitNormal.z);

					*resultRotation = tm.GetRotation();
				}
				*resultPosition = sceneColl.position;
			} else {
				*resultPosition += velocityRandomized;
			}
			*/

			// New version
			{
				VC3 hitNormal(0, 1.f, 0);
				if(sceneColl.hit)
				{
					hitNormal = sceneColl.plane_normal;
					*resultPosition = sceneColl.position;
				}
				else
				{
					*resultPosition += velocityRandomized;
					VC2 p2(resultPosition->x, resultPosition->z);
					hitNormal = gameScene->getTerrain()->getFaceNormal(p2);
				}

				{
					if(sceneColl.hit)
						hitWall = true;

		/*
		VC3 y = dir;
		VC3 z = hitNormal;
		y -= hitNormal * y.GetDotWith(hitNormal);
		VC3 x = z.GetCrossWith(y);
		*/

		VC3 x = dir;
		x.y = 0.f;
		x.Normalize();
		x -= hitNormal * x.GetDotWith(hitNormal);
		VC3 y = -x.GetCrossWith(hitNormal);
		VC3 z = hitNormal;

		MAT tm;
		tm.Set(0, x.x);
		tm.Set(1, x.y);
		tm.Set(2, x.z);
		tm.Set(4, y.x);
		tm.Set(5, y.y);
		tm.Set(6, y.z);
		tm.Set(8, z.x);
		tm.Set(9, z.y);
		tm.Set(10, z.z);

		resultRotation->MakeFromAngles(0.f, 0.f, -PI*0.5f);
		*resultRotation = (*resultRotation) * tm.GetRotation();

					/*
					VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f);
					x.Normalize();
					x -= hitNormal * x.GetDotWith(hitNormal);
					VC3 y = -x.GetCrossWith(hitNormal);

					assert(fabsf(x.GetDotWith(y)) < 0.0001f);
					assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f);

					MAT tm;
					tm.Set(0, x.x);
					tm.Set(1, x.y);
					tm.Set(2, x.z);
					tm.Set(4, y.x);
					tm.Set(5, y.y);
					tm.Set(6, y.z);
					tm.Set(8, hitNormal.x);
					tm.Set(9, hitNormal.y);
					tm.Set(10, hitNormal.z);

					*resultRotation = tm.GetRotation();
					*/
				}
			}


			// TODO: some kind of terrain raytrace maybe...?
			// should collide to walls, etc.
		}

		// if downward positioning...
		if (positioning == DecalPositionCalculator::DECAL_POSITIONING_DOWNWARD)
		{
			if (positionRandom > 0)
			{
				// TODO: add a random xz-offset to result position
				//*resultPosition += randomizedOffset;
				resultPosition->x += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
				resultPosition->z += float((SystemRandom::getInstance()->nextInt() % (positionRandom * 2 + 1)) - positionRandom) / 100.0f;
			}			

			/*
			// psd
			{
				VC2 p2(resultPosition->x, resultPosition->z);
				VC3 hitNormal = gameScene->getTerrain()->getFaceNormal(p2);

				VC3 x(rand() % 1000 / 999.f, 0, rand() % 1000 / 999.f);
				x.Normalize();
				x -= hitNormal * x.GetDotWith(hitNormal);
				VC3 y = -x.GetCrossWith(hitNormal);

				assert(fabsf(x.GetDotWith(y)) < 0.0001f);
				assert(fabsf(x.GetDotWith(hitNormal)) < 0.0001f);

				MAT tm;
				tm.Set(0, x.x);
				tm.Set(1, x.y);
				tm.Set(2, x.z);
				tm.Set(4, y.x);
				tm.Set(5, y.y);
				tm.Set(6, y.z);
				tm.Set(8, hitNormal.x);
				tm.Set(9, hitNormal.y);
				tm.Set(10, hitNormal.z);

				*resultRotation = tm.GetRotation();
			}
			*/
			VC3 fooNormal;
			calculateDecalRotation(gameScene, *resultPosition, *resultRotation, 0.f, fooNormal);
		}

		// now check that we're still inside map boundaries
		if (!gameMap->isWellInScaledBoundaries(resultPosition->x, resultPosition->z))
		{
			// out of map.
			return false;
		}

		// then fix decal height to ground height
		if (positioning == DecalPositionCalculator::DECAL_POSITIONING_DOWNWARD
			|| positioning == DecalPositionCalculator::DECAL_POSITIONING_VELOCITY)
		{
			if (!hitWall)
			{
				resultPosition->y = gameMap->getScaledHeightAt(resultPosition->x, resultPosition->z);
			}
		}

		// check that not on top of metal grid area...
		if (game::MaterialManager::isMaterialUnderPosition(gameMap, 
			*resultPosition, MATERIAL_METAL_GRATE))
		{
			// on top of grid, no decal here.
			return false;
		}

		// TODO: check that not inside a wall, terrainobject, etc.
		// if so, return false

		return true;
	}
	void PhysicsContactEffectManager::physicsContact(const PhysicsContact &contact)
	{
		// WARNING: unsafe IGamePhysicsObject -> AbstractPhysicsObject casts!
		AbstractPhysicsObject *o1 = (AbstractPhysicsObject *)contact.obj1;
		AbstractPhysicsObject *o2 = (AbstractPhysicsObject *)contact.obj2;
		//assert(o1 != NULL);
		//assert(o2 != NULL);
		assert(contact.physicsObject1);
		assert(contact.physicsObject2);

#ifdef PHYSICS_PHYSX
		int sm1 = contact.physicsObject1->getIntData();
		int sm2 = contact.physicsObject2->getIntData();
		if(sm1 == SOUNDMATERIALPARSER_NO_SOUND_INDEX || sm2 == SOUNDMATERIALPARSER_NO_SOUND_INDEX)
		{
			return;
		}
#else
		if (o1->getSoundMaterial() == SOUNDMATERIALPARSER_NO_SOUND_INDEX
			|| o2->getSoundMaterial() == SOUNDMATERIALPARSER_NO_SOUND_INDEX)
		{
			return;
		}
#endif

		const util::SoundMaterialParser::SoundMaterialList &smlist = impl->soundmp->getSoundMaterials();
		for (int i = 0; i < 2; i++)
		{
			AbstractPhysicsObject *o = o1;
			if (i == 1) 
			{
				o = o2;
			}
#ifdef PHYSICS_PHYSX
			int smindex = sm1;
			if (i == 1) 
			{
				smindex = sm2;
			}
			assert(smindex >= 0 && smindex < (int)smlist.size());
#else
			int smindex = o->getSoundMaterial();
#endif

			bool makeEffect = false;
			VC3 effectpos;

			if(o)
			{
				if(contact.contactForceLen >= smlist[smindex].requiredEffectForce)
				{
					effectpos = contact.contactPosition;

					VC3 accel = o->getAcceleration();
					VC3 angaccel = o->getAngularAcceleration();

					if (accel.GetSquareLength() >= smlist[smindex].requiredEffectAcceleration * smlist[smindex].requiredEffectAcceleration
						|| angaccel.GetSquareLength() >= smlist[smindex].requiredEffectAngularAcceleration * smlist[smindex].requiredEffectAngularAcceleration)
					{
						makeEffect = true;
					}

				}
			}
			else
			{
				if(contact.contactForceLen >= smlist[smindex].requiredEffectForce)
				{
					makeEffect = true;
					effectpos = contact.contactPosition;
				}
			}

			if(makeEffect)
			{
				if (o)
				{
					if (impl->game->gameTimer < o->getLastEffectTick() + (smlist[smindex].effectMaxRate / GAME_TICK_MSEC))
					{
						makeEffect = false;
					} else {
						o->setLastEffectTick(impl->game->gameTimer);
					}
				}
			}

			if(makeEffect)
			{
				std::vector<std::string> effectlist = smlist[smindex].effects;
				if (effectlist.size() > 0)
				{
					float effectFactor = 1.0f;
					if (smlist[smindex].requiredEffectForce > 0.0f)
					{
						// 0% - 100% effect factor (100% required force - 200% required force)
						effectFactor = (contact.contactForceLen / smlist[smindex].requiredEffectForce) - 1.0f;
						if (effectFactor > 1.0f)
							effectFactor = 1.0f;

						assert(effectFactor >= 0.0f);
						assert(effectFactor <= 1.0f);
					}

					int effnum = (int)(effectFactor * (effectlist.size() - 1));
					if (effnum < 0) effnum = 0;
					if (effnum >= (int)effectlist.size()) effnum = (int)effectlist.size() - 1;
					const char *effname = effectlist[effnum].c_str();

					ui::VisualEffectManager *vefman = impl->game->gameUI->getVisualEffectManager();
					if (vefman != NULL)
					{
						assert(effname != NULL);

						// TODO: optimize this!!!
						int visualEffId = vefman->getVisualEffectIdByName(effname);

						if (visualEffId != -1)
						{
							// TODO: proper lifetime
							int lifetime = GAME_TICKS_PER_SECOND / 2;
							VisualEffect *vef = vefman->createNewManagedVisualEffect(visualEffId, lifetime, NULL, NULL,
								effectpos, effectpos, VC3(0,0,0), VC3(0,0,0), impl->game);

							if (vef == NULL)
							{
								Logger::getInstance()->error("PhysicsContactEffectManager::physicsContact - Failed to create visual effect.");
								Logger::getInstance()->debug(effname);
							}
						} else {
							Logger::getInstance()->error("PhysicsContactEffectManager::physicsContact - Given visual effect name not found.");
							Logger::getInstance()->debug(effname);
						}
					}
				}
			}
		}
	}
Beispiel #28
0
VC3 AlignUnits::getMovedPosition(const VC3 &position, IStorm3D_Camera &camera, bool *updated) const
{
	VC3 result = position;
	float factor = .005f;
	bool useGrid = false;

	if((GetKeyState(VK_SHIFT) & 0x80))
		factor = .2f;

	if((GetKeyState(VK_CONTROL) & 0x80) == 0)
		useGrid = true;

	factor *= getTimeDelta();

	VC3 y = camera.GetTarget() - camera.GetPosition();
	y.y = 0;
	y.Normalize();
	VC3 x = VC3(0.f, 1.f, 0.f).GetCrossWith(y);

#ifdef PROJECT_AOV
	x = VC3(1, 0, 0);
	y = VC3(0, 0, 1);
#endif

	y *= 40.f;
	x *= 40.f;

	// new: if ctrl was not down, use grid to move objects
	static int lastGridMoveTime = 0;
	long curTime = timeGetTime();

	if (useGrid)
	{
		if (fabsf(x.x) > fabsf(x.z))
		{
			x = VC3(x.x,0,0);
			y = VC3(0,0,y.z);
		} else {
			x = VC3(0,0,x.z);
			y = VC3(y.x,0,0);
		}
		if (x.GetSquareLength() > 0.0001f)
		{
			x.Normalize();
			x *= data->gridX;
		} else {
			x = VC3(0,0,0);
		}
		if (y.GetSquareLength() > 0.0001f)
		{
			y.Normalize();
			y *= data->gridY;
		} else {
			y = VC3(0,0,0);
		}

		if((GetKeyState(VK_SHIFT) & 0x80))
		{
//#ifdef PROJECT_AOV
//			x *= 10.0f; 
//			y *= 10.0f; 
//#else
			x *= 10.0f; 
			y *= 10.0f; 
//#endif
		}

		if (curTime < lastGridMoveTime + 100)
		{
			factor = 0.0f;
		} else {
			factor = 1.0f;
		}
	}
	// end of new grid thingy

	if(updated)
		*updated = false;

	if (factor != 0.0f)
	{
		if((GetKeyState(VK_UP) & 0x80))
		{
			result += y * factor;
			if(updated)
				*updated = true;
			lastGridMoveTime = curTime;
		}
		if((GetKeyState(VK_DOWN) & 0x80))
		{
			result -= y * factor;
			if(updated)
				*updated = true;
			lastGridMoveTime = curTime;
		}
		if((GetKeyState(VK_RIGHT) & 0x80))
		{
			result += x * factor;
			if(updated)
				*updated = true;
			lastGridMoveTime = curTime;
		}
		if((GetKeyState(VK_LEFT) & 0x80))
		{
			result -= x * factor;
			if(updated)
				*updated = true;
			lastGridMoveTime = curTime;
		}
	}

	return result;
}
	void CameraScripting::process(util::ScriptProcess *sp, 
		int command, floatint intFloat, char *stringData, ScriptLastValueType *lastValue,
		GameScriptData *gsd, Game *game)
	{
		int intData = intFloat.i;
		switch(command)
		{
		case GS_CMD_CAMERAPOSITION:
			// TODO: proper handling of players in netgame
			gsd->position = game->gameUI->getGameCamera()->getPosition();

#ifdef LEGACY_FILES
			// ok
#else
			sp->warning("CameraScripting::process - cameraPosition deprecated, use actualCameraPosition instead.");
#endif
			break;

		case GS_CMD_LISTENERPOSITION:
			// TODO: proper handling of players in netgame
			
			// TODO: real listener position, this is just an approximation...
			// (that is, using camera position as the camera position for now)
			//gsd->position = game->gameUI->getGameCamera()->getPosition();
			gsd->position = game->gameUI->getListenerPosition();
			break;

		case GS_CMD_SETCAMERAPOSITIONNEAR:
			// TODO: proper handling of players in netgame
			game->gameUI->getGameCamera()->setPositionNear(gsd->position.x, gsd->position.z);
			break;

		case GS_CMD_SETCAMERAPOSITION:
			{
				// new: global offsetting via 2 pivots and rotation around the nwe "pivot".
				VC3 pos = gsd->position;

				pos -= Ani::getGlobalOffsetSource();
				float angle = Ani::getGlobalRotation();

				float tmpX = pos.x;
				pos.x = pos.x * cosf(UNIT_ANGLE_TO_RAD(angle)) + pos.z * sinf(UNIT_ANGLE_TO_RAD(angle));
				pos.z = pos.z * cosf(UNIT_ANGLE_TO_RAD(angle)) - tmpX * sinf(UNIT_ANGLE_TO_RAD(angle));

				pos += Ani::getGlobalOffsetTarget();

				game->gameUI->getGameCamera()->setPosition(pos);
				game->gameUI->getGameCamera()->doMovement(1);
			}
			break;

		case GS_CMD_rotateCameraAroundPosition:
			game->gameUI->getGameCamera()->rotateAroundPosition(gsd->position, *lastValue);
			game->gameUI->getGameCamera()->doMovement(1);
			break;

		case GS_CMD_SETCAMERAANGLE:
			// TODO: proper handling of players in netgame
			if (intData >= 0 || intData < 360)
			{
				float angle = (float)intData;
				angle += Ani::getGlobalRotation();
				if (angle < 0) angle += 360.0f;
				if (angle > 360.0f) angle -= 360.0f;

				game->gameUI->getGameCamera()->setAngleY(angle);
			} else {
				sp->error("GameScripting::process - setCameraAngle parameter bad.");
			}
			game->gameUI->getGameCamera()->doMovement(1);
			break;
		case GS_CMD_SETCAMERAANGLEFLOAT:
			{
				float floatData = intFloat.f;
				if (floatData >= 0.0f || floatData < 360.0f)
				{
					floatData -= Ani::getGlobalRotation();
					if (floatData < 0) floatData += 360.0f;
					if (floatData > 360.0f) floatData -= 360.0f;

					game->gameUI->getGameCamera()->setAngleY(floatData);
				} else {
					sp->error("GameScripting::process - setCameraAngleFloat parameter bad.");
				}
				game->gameUI->getGameCamera()->doMovement(1);
			}
			break;

		case GS_CMD_SETCAMERAANGLETOVALUE:
			game->gameUI->getGameCamera()->setAngleY((float)(90 - *lastValue));
			game->gameUI->getGameCamera()->doMovement(1);
			break;

		case GS_CMD_GETCAMERAANGLE:
			{
				*lastValue = (int)game->gameUI->getGameCamera()->getAngleY();
				*lastValue = 270 - *lastValue;
				if (*lastValue < 0) *lastValue += 360;
			}
			break;

		case GS_CMD_GETCAMERABETAANGLE:
			{
				*lastValue = (int)game->gameUI->getGameCamera()->getBetaAngle();
			}
			break;

		case GS_CMD_SETCAMERABETAANGLE:
			// TODO: proper handling of players in netgame
			if (intData >= -180 || intData < 180)
			{
				game->gameUI->getGameCamera()->setBetaAngle((float)intData);
			} else {
				sp->error("GameScripting::process - setCameraBetaAngle parameter bad.");
			}
			game->gameUI->getGameCamera()->doMovement(1);
			break;

		case GS_CMD_SETCAMERABETAANGLEFLOAT:
			{
				float floatData = intFloat.f;
				if (floatData >= -180 || floatData < 180)
				{
					game->gameUI->getGameCamera()->setBetaAngle(floatData);
				} else {
					sp->error("GameScripting::process - setCameraBetaAngleFloat parameter bad.");
				}
				game->gameUI->getGameCamera()->doMovement(1);
			}
			break;

		case GS_CMD_SETCAMERAZOOM:
			// TODO: proper handling of players in netgame
			game->gameUI->getGameCamera()->setZoom((float)intData);
			game->gameUI->getGameCamera()->doMovement(1);
			break;

		case GS_CMD_SETCAMERAFLOATZOOM:
			if (stringData != NULL)
			{
				game->gameUI->getGameCamera()->setZoom((float)atof(stringData));
				game->gameUI->getGameCamera()->doMovement(1);
			} else {
				sp->error("GameScripting::process - setCameraFloatZoom parameter missing.");
			}
			break;

		case GS_CMD_SELECTCAMERA:
			if (stringData != NULL)
			{
				// oh yeah! copy & paste programming ahead...
				if (strncmp(stringData, "cinematic1,", 11) == 0)
				{
					GameCamera *curcam = game->gameUI->getGameCamera();
					game->gameUI->selectCamera(GAMEUI_CAMERA_CINEMATIC1);
					int itime = str2int(&stringData[11]);
					if (itime != 0)
						game->gameUI->getGameCamera()->interpolateFrom(curcam, (float)itime);
					else
						game->gameUI->getGameCamera()->interpolateFrom(game->gameUI->getGameCamera(), 0);
					game->gameUI->getGameCamera()->doMovement(1);
					break;
				}
				if (strncmp(stringData, "cinematic2,", 11) == 0)
				{
					GameCamera *curcam = game->gameUI->getGameCamera();
					game->gameUI->selectCamera(GAMEUI_CAMERA_CINEMATIC2);
					int itime = str2int(&stringData[11]);
					if (itime != 0)
						game->gameUI->getGameCamera()->interpolateFrom(curcam, (float)itime);
					else
						game->gameUI->getGameCamera()->interpolateFrom(game->gameUI->getGameCamera(), 0);
					game->gameUI->getGameCamera()->doMovement(1);
					break;
				}
				if (strncmp(stringData, "normal,", 7) == 0)
				{
					GameCamera *curcam = game->gameUI->getGameCamera();
					game->gameUI->selectCamera(GAMEUI_CAMERA_NORMAL);
					int itime = str2int(&stringData[7]);
					if (itime != 0)
						game->gameUI->getGameCamera()->interpolateFrom(curcam, (float)itime);
					else
						game->gameUI->getGameCamera()->interpolateFrom(game->gameUI->getGameCamera(), 0);
					game->gameUI->getGameCamera()->doMovement(1);
					break;
				}
				if (strncmp(stringData, "tactical,", 9) == 0)
				{
					GameCamera *curcam = game->gameUI->getGameCamera();
					game->gameUI->selectCamera(GAMEUI_CAMERA_TACTICAL);
					int itime = str2int(&stringData[9]);
					if (itime != 0)
						game->gameUI->getGameCamera()->interpolateFrom(curcam, (float)itime);
					else
						game->gameUI->getGameCamera()->interpolateFrom(game->gameUI->getGameCamera(), 0);
					game->gameUI->getGameCamera()->doMovement(1);
					break;
				}
				sp->error("GameScripting::process - selectCamera parameter bad.");
			} else {
				sp->error("GameScripting::process - selectCamera parameter expected.");
			}
			break;
			
		case GS_CMD_SETCAMERAMOVEMENTON:
			// TODO: proper handling of players in netgame
			if (stringData != NULL)
			{
				GameCamera::CAMERA_MOVE moveNum = GameCamera::getCameraMoveByName(stringData);
				if (moveNum != GameCamera::CAMERA_MOVE_INVALID)
				{
					game->gameUI->getGameCamera()->setMovement(moveNum, true);
				} else {
					sp->error("GameScripting::process - setCameraMovementOn parameter invalid.");
				}
			} else {
				sp->error("GameScripting::process - setCameraMovementOn parameter missing.");
			}
			break;

		case GS_CMD_SETCAMERAMOVEMENTOFF:
			// TODO: proper handling of players in netgame
			if (stringData != NULL)
			{
				GameCamera::CAMERA_MOVE moveNum = GameCamera::getCameraMoveByName(stringData);
				if (moveNum != GameCamera::CAMERA_MOVE_INVALID)
				{
					game->gameUI->getGameCamera()->setMovement(moveNum, false);
				} else {
					sp->error("GameScripting::process - setCameraMovementOff parameter invalid.");
				}
			} else {
				sp->error("GameScripting::process - setCameraMovementOff parameter missing.");
			}
			break;

		case GS_CMD_SETCAMERAMODE:
			// TODO: proper handling of players in netgame
			if (stringData != NULL)
			{
				GameCamera::CAMERA_MODE modeNum = GameCamera::getCameraModeByName(stringData);
				if (modeNum != GameCamera::CAMERA_MODE_INVALID)
				{
					game->gameUI->getGameCamera()->setMode(modeNum);
					game->gameUI->getGameCamera()->doMovement(1);
				} else {
					sp->error("GameScripting::process - setCameraMode parameter invalid.");
				}
			} else {
				sp->error("GameScripting::process - setCameraMode parameter missing.");
			}
			break;

		case GS_CMD_SETCAMERATIMEFACTOR:
			if (stringData != NULL)
			{
				float timeFactor = (float)atof(stringData);
				if (timeFactor < 0.1f) timeFactor = 0.1f;
				if (timeFactor > 10.0f) timeFactor = 10.0f;
				game->gameUI->setCameraTimeFactor(timeFactor);
			} else {
				sp->error("GameScripting::process - setCameraTimeFactor parameter missing.");
			}
			break;

		case GS_CMD_ISCAMERAZOOMLESSTHAN:
			if (game->gameUI->getGameCamera()->getZoom() < (float)intData)
			{
				*lastValue = 1;
			} else {
				*lastValue = 0;
			}
			break;

		case GS_CMD_ISCAMERAZOOMGREATERTHAN:
			if (game->gameUI->getGameCamera()->getZoom() > (float)intData)
			{
				*lastValue = 1;
			} else {
				*lastValue = 0;
			}
			break;

		case GS_CMD_SETCAMERAFOV:
			game->gameUI->getGameCamera()->setFOV((float)intData);
			break;

		case GS_CMD_setCameraFOVFloat:
			{
				float floatData = intFloat.f;
				game->gameUI->getGameCamera()->setFOV(floatData);
			}
			break;

		case GS_CMD_COPYCAMERATO:
			if (stringData != NULL)
			{
				int curnum = game->gameUI->getCameraNumber();
				GameCamera *curcam = game->gameUI->getGameCamera();
				bool paramok = false;
				if (strcmp(stringData, "cinematic1") == 0)
				{
					game->gameUI->selectCamera(GAMEUI_CAMERA_CINEMATIC1);
					paramok = true;
				}
				if (strcmp(stringData, "cinematic2") == 0)
				{
					game->gameUI->selectCamera(GAMEUI_CAMERA_CINEMATIC2);
					paramok = true;
				}
				if (strcmp(stringData, "normal") == 0)
				{
					game->gameUI->selectCamera(GAMEUI_CAMERA_NORMAL);
					paramok = true;
				}
				if (strcmp(stringData, "tactical") == 0)
				{
					game->gameUI->selectCamera(GAMEUI_CAMERA_TACTICAL);
					paramok = true;
				}
				game->gameUI->getGameCamera()->copyFrom(curcam);
				game->gameUI->selectCamera(curnum);
				game->gameUI->getGameCamera()->doMovement(1);
				if (!paramok)
				{
					sp->error("GameScripting::process - selectCamera parameter bad.");
				}
			} else {
				sp->error("GameScripting::process - selectCamera parameter expected.");
			}
			break;

		case GS_CMD_setMapView:
			{

				bool showMap = stringData != NULL ? true : false;

				if(strcmp("stringData", "0") == 0)
					showMap = false;

				IStorm3D *storm = game->getGameUI()->getStorm3D();

				int dummy1 = 0, dummy2 = 0;

				if(showMap)
				{
					game->gameScripting->runSingleSimpleStringCommand( "hideGUI", "", &dummy1, &dummy2 );
					game->gameScripting->runSingleSimpleStringCommand( "hideAllUnits", "", &dummy1, &dummy2 );

					game->getEnvironmentalEffectManager()->enableSunlight();
					game->getEnvironmentalEffectManager()->setSunlightDirection ( VC3( 1,-1, 1) );
					game->getEnvironmentalEffectManager()->setSunlightColor ( COL(1,1,1) );

				} else
				{
					game->gameScripting->runSingleSimpleStringCommand( "showAllUnits", "", &dummy1, &dummy2 );
					game->gameScripting->runSingleSimpleStringCommand( "showGUI", "", &dummy1, &dummy2 );
					game->getEnvironmentalEffectManager()->disableSunlight();
				}

				if(showMap)
				{

					float scrAspect;
					if(storm->getRenderTarget(0))
						scrAspect = (float)storm->getRenderTarget(0)->getWidth() / storm->getRenderTarget(0)->getHeight();
					else
						scrAspect = (float)storm->GetScreenSize().width / storm->GetScreenSize().height;

					int areaX = -1, areaY = -1;
					// if stringData is in form NxN, where N is a number...
					if(  strlen(stringData) == 3 &&
						( stringData[0] >='1' && stringData[0] <='9' ) &&
						( stringData[1] == 'x' ) &&
						( stringData[2] >='1' && stringData[2] <='9' ) )
					{
						areaX = stringData[0] - '1';
						areaY = stringData[2] - '1';
					}

					game->gameUI->getGameCamera()->setForceMapView(true, areaX, areaY, 1024, 1024, scrAspect );

				}
				else
					game->gameUI->getGameCamera()->setForceMapView(false);

			}
			break;

		case GS_CMD_ROTATECAMERATOWARDUNIT:
			if (gsd->unit != NULL)
			{
				VC3 upos = gsd->unit->getPosition();
				VC3 campos = game->gameUI->getGameCamera()->getPosition();
				VC3 midpos(0,0,0);
				VC3 rotation(0,0,0);
				float scale;
				
				util::ObjectStretchingCalculator::calculateStretchValues(
					campos, upos, &midpos, &rotation, &scale);

				rotation.y = 270 - rotation.y;
				if (rotation.y < 0) rotation.y += 360;
				game->gameUI->getGameCamera()->setAngleY(rotation.y);
				game->gameUI->getGameCamera()->setBetaAngle(-rotation.x);
				game->gameUI->getGameCamera()->doMovement(1);

			} else {
				sp->warning("GameScripting::process - Attempt to rotateCameraTowardUnit for null unit.");
			} 					
			break;

		case GS_CMD_SETCAMERAHEIGHT:
			// TODO: proper handling of players in netgame
			game->gameUI->getGameCamera()->setHeight((float)intData);
			game->gameUI->getGameCamera()->doMovement(1);
			break;

		case GS_CMD_SHAKECAMERANEARPOSITIONSHORT:
			game->gameUI->getGameCamera()->setShakeEffect(intData, 500, gsd->position);
			break;

		case GS_CMD_SHAKECAMERANEARPOSITIONMEDIUM:
			game->gameUI->getGameCamera()->setShakeEffect(intData, 2500, gsd->position);
			break;

		case GS_CMD_SHAKECAMERANEARPOSITIONLONG:
			game->gameUI->getGameCamera()->setShakeEffect(intData, 8000, gsd->position);
			break;

		case GS_CMD_SETCAMERAINTERPOLATIONTYPE:
			if (stringData != NULL)
			{
				if (strcmp(stringData, "sinwave") == 0)
				{
					game->gameUI->getGameCamera()->setSmoothCameraInterpolation(true);
				}
				else if (strcmp(stringData, "linear") == 0)
				{
					game->gameUI->getGameCamera()->setSmoothCameraInterpolation(false);
				} 
				else 
				{
					sp->error("GameScripting::process - setCameraInterpolationType parameter bad.");
				}
			} else {
				// TODO: error
			}
			break;

		case GS_CMD_SETCAMERARANGE:
			if (intData > 0)
			{
				game->gameUI->setCameraRange((float)intData);
			} else {
				sp->error("GameScripting::process - setCameraRange parameter out of range (positive range value expected).");
			}
			break;

		case GS_CMD_GETCAMERARANGE:
			*lastValue = (int)game->gameUI->getCameraRange();
			break;

		case GS_CMD_RESTORECAMERARANGE:
			game->gameUI->restoreCameraRange();
			break;

		case GS_CMD_SETCAMERATARGETDISTANCE:
			if (game->inCombat)
			{
				game->gameUI->getGameCamera()->setTargetDistance((float)intData);
			}
			break;

		case GS_CMD_RESTORECAMERATARGETDISTANCE:
			if (game->inCombat)
			{
				game->gameUI->getGameCamera()->restoreDefaultTargetDistance();
			}
			break;

		case GS_CMD_setCameraAutozoomIndoor:
			if (game->inCombat)
			{
				float floatData = intFloat.f;
				ui::CameraAutozoomer::setAreaZoom(ui::CameraAutozoomer::CAMERA_AUTOZOOMER_AREA_INDOOR, floatData);
			}
			break;

		case GS_CMD_setCameraAutozoomOutdoor:
			if (game->inCombat)
			{
				float floatData = intFloat.f;
				ui::CameraAutozoomer::setAreaZoom(ui::CameraAutozoomer::CAMERA_AUTOZOOMER_AREA_OUTDOOR, floatData);
			}
			break;

		case GS_CMD_saveCameraAutozoom:
			if (game->inCombat)
			{
				ui::CameraAutozoomer::saveCheckpointState();
			}
			break;

		case GS_CMD_loadCameraAutozoom:
			if (game->inCombat)
			{
				ui::CameraAutozoomer::loadCheckpointState();
			}
			break;

		case GS_CMD_setCameraUpVector:
			if (stringData != NULL)
			{
				VC3 upvec = VC3(0,0,0);
				if (gs_tricoord_param(stringData, &upvec))
				{
					if (!(upvec.GetSquareLength() > 0.99f * 0.99f
						&& upvec.GetSquareLength() < 1.01f * 1.01f))
					{
						sp->warning("CameraScripting::process - setCameraUpVector parameter is not a normalized vector (will be normalized).");
					}
					if (!(upvec.GetSquareLength() > 0.001f * 0.001f))
					{
						sp->warning("CameraScripting::process - setCameraUpVector parameter is a zero length or invalid vector (falling back to default).");
						upvec = VC3(0,1,0);
					}
					upvec.Normalize();
					game->gameUI->getGameCamera()->setUpVector(upvec);
				} else {
					sp->error("CameraScripting::process - setCameraUpVector parameter invalid (expected vector in format x,y,z).");
				}
			} else {
				sp->error("CameraScripting::process - setCameraUpVector parameter missing (expected vector in format x,y,z).");
			}
			break;

		case GS_CMD_setCameraNearClipValue:
			{
				float floatData = intFloat.f;
				if( game && game->gameScene && game->gameScene->getStormScene() && game->gameScene->getStormScene()->GetCamera() )
					game->gameScene->getStormScene()->GetCamera()->SetZNear( floatData );
			}
			break;

		case GS_CMD_setCameraNearClipDefault:
			if( game && game->gameScene && game->gameScene->getStormScene() && game->gameScene->getStormScene()->GetCamera() )
				game->gameScene->getStormScene()->GetCamera()->SetZNearDefault();
			break;

		case GS_CMD_setCameraPositionOffsetXToFloatValue:
			if (game->inCombat)
			{
				VC3 tmp = game->gameUI->getGameCamera()->getPositionOffset();
				tmp.x = gsd->floatValue;
				game->gameUI->getGameCamera()->setPositionOffset(tmp);
			}
			break;

		case GS_CMD_setCameraPositionOffsetYToFloatValue:
			if (game->inCombat)
			{
				VC3 tmp = game->gameUI->getGameCamera()->getPositionOffset();
				tmp.y = gsd->floatValue;
				game->gameUI->getGameCamera()->setPositionOffset(tmp);
			}			
			break;

		case GS_CMD_setCameraPositionOffsetZToFloatValue:
			if (game->inCombat)
			{
				VC3 tmp = game->gameUI->getGameCamera()->getPositionOffset();
				tmp.z = gsd->floatValue;
				game->gameUI->getGameCamera()->setPositionOffset(tmp);
			}						
			break;

		case GS_CMD_setCameraTargetOffsetXToFloatValue:
			if (game->inCombat)
			{
				VC3 tmp = game->gameUI->getGameCamera()->getTargetOffset();
				tmp.x = gsd->floatValue;
				game->gameUI->getGameCamera()->setTargetOffset(tmp);
			}
			break;

		case GS_CMD_setCameraTargetOffsetYToFloatValue:
			if (game->inCombat)
			{
				VC3 tmp = game->gameUI->getGameCamera()->getTargetOffset();
				tmp.y = gsd->floatValue;
				game->gameUI->getGameCamera()->setTargetOffset(tmp);
			}			
			break;

		case GS_CMD_setCameraTargetOffsetZToFloatValue:
			if (game->inCombat)
			{
				VC3 tmp = game->gameUI->getGameCamera()->getTargetOffset();
				tmp.z = gsd->floatValue;
				game->gameUI->getGameCamera()->setTargetOffset(tmp);
			}						
			break;

		case GS_CMD_setCameraTargetOffsetAtPosition:
			if (game->inCombat)
			{
				VC3 targpos = game->gameUI->getGameCamera()->getTargetPosition();
				VC3 diff = gsd->position - targpos;
				game->gameUI->getGameCamera()->setTargetOffset(diff);
			}						
			break;

		case GS_CMD_setCameraPositionOffsetAtPosition:
			if (game->inCombat)
			{
				VC3 campos = game->gameUI->getGameCamera()->getPosition();
				VC3 diff = gsd->position - campos;
				game->gameUI->getGameCamera()->setPositionOffset(diff);
			}						
			break;

		case GS_CMD_disableDirectCameraControls:
			if (game->inCombat)
			{
				game->gameUI->getGameCamera()->setDirectControlsEnabled(false);
			}
			break;

		case GS_CMD_enableDirectCameraControls:
			if (game->inCombat)
			{
				game->gameUI->getGameCamera()->setDirectControlsEnabled(true);
			}						
			break;

		case GS_CMD_updateCamera:
			{
				game->gameUI->getGameCamera()->doMovement(0);
			}
			break;

		case GS_CMD_setCameraAreaType:
			{
				cameraAreaParameters.type = intData;
			}
			break;

		case GS_CMD_setCameraAreaCorner1ToPosition:
			{
				VC3 pos = gsd->position;
				cameraAreaParameters.corner[0] = pos;				
			}
			break;

		case GS_CMD_setCameraAreaCorner2ToPosition:
			{
				VC3 pos = gsd->position;
				cameraAreaParameters.corner[1] = pos;				
			}
			break;

		case GS_CMD_setCameraAreaCorner3ToPosition:
			{
				VC3 pos = gsd->position;
				cameraAreaParameters.corner[2] = pos;				
			}
			break;

		case GS_CMD_setCameraAreaCorner4ToPosition:
			{
				VC3 pos = gsd->position;
				cameraAreaParameters.corner[3] = pos;				
			}
			break;

		case GS_CMD_setCameraAreaFOV:
			{
				float floatData = intFloat.f;
				cameraAreaParameters.FOV = floatData;			
			}
			break;

		case GS_CMD_setCameraAreaAngle:
			{
				float floatData = intFloat.f;
				cameraAreaParameters.angle = floatData;			
			}
			break;

		case GS_CMD_setCameraAreaBetaAngle:
			{
				float floatData = intFloat.f;
				cameraAreaParameters.betaAngle = floatData;			
			}
			break;

		case GS_CMD_setCameraAreaBank:
			{
				float floatData = intFloat.f;
				cameraAreaParameters.bank = floatData;			
			}
			break;

		case GS_CMD_setCameraAreaOffsetX:
			{
				float floatData = intFloat.f;
				cameraAreaParameters.offset.x = floatData;			
			}
			break;

		case GS_CMD_setCameraAreaOffsetY:
			{
				float floatData = intFloat.f;
				cameraAreaParameters.offset.y = floatData;			
			}
			break;

		case GS_CMD_setCameraAreaOffsetZ:
			{
				float floatData = intFloat.f;
				cameraAreaParameters.offset.z = floatData;			
			}
			break;

		case GS_CMD_setCameraAreaFollowX:
			{
				float floatData = intFloat.f;
				cameraAreaParameters.follow.x = floatData*0.01f;			
			}
			break;

		case GS_CMD_setCameraAreaFollowY:
			{
				float floatData = intFloat.f;
				cameraAreaParameters.follow.y = floatData*0.01f;			
			}
			break;

		case GS_CMD_setCameraAreaFollowZ:
			{
				float floatData = intFloat.f;
				cameraAreaParameters.follow.z = floatData*0.01f;			
			}
			break;

		case GS_CMD_setCameraAreaTargetToPosition:
			{
				VC3 pos = gsd->position;
				cameraAreaParameters.target = pos;				
			}
			break;

		case GS_CMD_setCameraAreaAnimation:
			{
				cameraAreaParameters.animation = stringData;				
			}
			break;

		case GS_CMD_setCameraAreaGroup:
			{
				cameraAreaParameters.group = intData;
			}
			break;

		case GS_CMD_addCameraArea:
			{
				game->getGameUI()->getCameraSystem()->addCameraArea(new CameraAreaStreet(cameraAreaParameters.name, cameraAreaParameters.group, cameraAreaParameters.collision, cameraAreaParameters.corner[0], cameraAreaParameters.corner[1], cameraAreaParameters.corner[2], cameraAreaParameters.corner[3], cameraAreaParameters.angle, cameraAreaParameters.betaAngle, cameraAreaParameters.bank, cameraAreaParameters.distance, cameraAreaParameters.FOV, cameraAreaParameters.target, cameraAreaParameters.offset, cameraAreaParameters.follow, cameraAreaParameters.animation));
//				initializeCameraAreaParameters();
			}
			break;

		case GS_CMD_setCameraAreaAngleToValue:
			{
				float floatData = (float)(*lastValue);
				cameraAreaParameters.angle = floatData;			
			}
			break;

		case GS_CMD_setCameraAreaName:
			{
				cameraAreaParameters.name = stringData;				
			}
			break;

		case GS_CMD_setCameraAreaDistance:
			{
				float floatData = intFloat.f;
				cameraAreaParameters.distance = floatData;			
			}
			break;

		case GS_CMD_setCameraAreaCollision:
			{
				cameraAreaParameters.type = intData;
			}
			break;

		case GS_CMD_actualCameraPosition:
			gsd->position = game->gameUI->getGameCamera()->getActualInterpolatedPosition();
			break;

		case GS_CMD_moveCameraAngle:
			{
				float floatData = intFloat.f;
				game->getGameUI()->getCameraSystem()->moveCameraAngle(floatData);			
			}
			break;

		case GS_CMD_moveCameraBetaAngle:
			{
				float floatData = intFloat.f;
				game->getGameUI()->getCameraSystem()->moveCameraBetaAngle(floatData);			
			}
			break;

		case GS_CMD_moveCameraBank:
			{
				float floatData = intFloat.f;
				game->getGameUI()->getCameraSystem()->moveCameraBank(floatData);			
			}
			break;

		case GS_CMD_moveCameraDistance:
			{
				float floatData = intFloat.f;
				game->getGameUI()->getCameraSystem()->moveCameraDistance(floatData);			
			}
			break;

		case GS_CMD_moveCameraFOV:
			{
				float floatData = intFloat.f;
				game->getGameUI()->getCameraSystem()->moveCameraFOV(floatData);			
			}
			break;

		case GS_CMD_clearCameraAreas:
			{
				game->getGameUI()->getCameraSystem()->clearCameraAreas();			
			}
			break;

			
		case GS_CMD_isCameraSelected:
			if (stringData != NULL)
			{
				// oh yeah! copy & paste programming ahead...
				if (strncmp(stringData, "cinematic1", 10) == 0)
				{
					*lastValue = game->gameUI->getCameraNumber() == GAMEUI_CAMERA_CINEMATIC1 ? 1 : 0;
					break;
				}
				if (strncmp(stringData, "cinematic2", 10) == 0)
				{
					*lastValue = game->gameUI->getCameraNumber() == GAMEUI_CAMERA_CINEMATIC2 ? 1 : 0;
					break;
				}
				if (strncmp(stringData, "normal", 6) == 0)
				{
					*lastValue = game->gameUI->getCameraNumber() == GAMEUI_CAMERA_NORMAL ? 1 : 0;
					break;
				}
				if (strncmp(stringData, "tactical", 8) == 0)
				{
					*lastValue = game->gameUI->getCameraNumber() == GAMEUI_CAMERA_TACTICAL ? 1 : 0;
					break;
				}
				*lastValue = 0;
				sp->error("GameScripting::process - isCameraSelected parameter bad.");
			} else {
				*lastValue = 0;
				sp->error("GameScripting::process - isCameraSelected parameter expected.");
			}
			break;

		default:
			sp->error("CameraScripting::process - Unknown command.");
			assert(0);
		}
	}
void ParticleArea::biasValues(const VC3 &position, VC3 &velocity) const
{
	float wx = position.x;
	float wy = position.z;

	if(gameMap->isWellInScaledBoundaries(wx, wy))
	{
		float height = position.y / gameMap->getScaleHeight();
		int x = gameMap->scaledToObstacleX(wx);
		int y = gameMap->scaledToObstacleY(wy);

		CoverMap *coverMap = gameMap->getCoverMap();
		CoverMap::COVER_DIRECTION dir = coverMap->getNearestCoverDirection(x, y);
		int distance = coverMap->getDistanceToNearestCover(x, y);

		{
			AreaMap *areaMap = gameMap->getAreaMap();
			int ax = x;
			int ay = y;

			if(dir == CoverMap::COVER_DIRECTION_N)
				ay -= distance;
			else if(dir == CoverMap::COVER_DIRECTION_NE)
			{
				int df = int(distance * 0.7071f);
				ax += df;
				ay -= df;
			}
			else if(dir == CoverMap::COVER_DIRECTION_E)
				ax += distance;
			else if(dir == CoverMap::COVER_DIRECTION_SE)
			{
				int df = int(distance * 0.7071f);
				ax += df;
				ay += df;
			}
			else if(dir == CoverMap::COVER_DIRECTION_S)
				ay += distance;
			else if(dir == CoverMap::COVER_DIRECTION_SW)
			{
				int df = int(distance * 0.7071f);
				ax -= df;
				ay += df;
			}
			else if(dir == CoverMap::COVER_DIRECTION_W)
				ax -= distance;
			else if(dir == CoverMap::COVER_DIRECTION_NW)
			{
				int df = int(distance * 0.7071f);
				ax -= df;
				ay -= df;
			}

			if(areaMap->isAreaAnyValue(ax, ay, AREAMASK_OBSTACLE_UNHITTABLE) || gameMap->getObstacleHeight(ax, ay) < 20)
				return;
		}

		if(distance > 0 && distance < 8)
		{
			float blendFactor = 1.f - (distance / 8.f);
			blendFactor *= 0.04f;
			float angle = ((dir - 1) * 45.f) * PI / 180.f;
			VC3 blendVector;
			blendVector.x = -sinf(angle);
			blendVector.z = cosf(angle);

			blendVector *= velocity.GetLength();
			blendVector *= blendFactor;
			velocity *= 1.f - blendFactor;
			velocity += blendVector;
		}
	}
}