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()); }
/*! \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; }
/*! \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; }
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); }
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; } }
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; }
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); } }
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); } } } }
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; }
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); } } } }
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); } }
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."); } }
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); } }
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); } } } } } }
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; } } }