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; }
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; } } } }
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 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); } } } }
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 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 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 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 ParticlePhysics::update() { if(!data->physics) return; data->actorBaseList.clear(); data->fluidBaseList.clear(); // Update physics actors { for(PhysicsActorList::iterator it = data->physicsActorList.begin(); it != data->physicsActorList.end(); ++it) { PhysicsActor *actor = *it; if(!actor->actor) continue; /* if(actor->actor) { VC3 velocity; actor->actor->getVelocity(velocity); float len = velocity.GetLength(); if(len > 1) { velocity /= len; actor->actor->setVelocity(velocity); } } */ #ifndef PHYSX_GRAVITY if(actor->force.GetSquareLength() > 0.01f) { if(!actor->forceUpdate && ++actor->sleepCounter % 10 == 0) { VC3 currentPos; actor->getPosition(currentPos); VC3 currentAngular; actor->actor->getAngularVelocity(currentAngular); if( currentPos.GetSquareRangeTo(actor->lastPosition1) < 0.00001f || currentAngular.GetSquareRangeTo(actor->lastAngular1) < 0.00001f || currentPos.GetSquareRangeTo(actor->lastPosition2) < 0.00001f || currentAngular.GetSquareRangeTo(actor->lastAngular2) < 0.00001f) { if(!actor->actor->isSleeping()) actor->actor->putToSleep(); } actor->lastPosition2 = actor->lastPosition1; actor->lastAngular2 = actor->lastAngular1; actor->lastPosition1 = currentPos; actor->lastAngular1 = currentAngular; } if(actor->forceUpdate || !actor->actor->isSleeping()) actor->actor->addVelocityChange(actor->force); actor->force = VC3(); } #else if(actor->forceUpdate) { VC3 base; actor->actor->getVelocity(base); VC3 newForce = base; newForce += actor->force; float len = newForce.GetSquareLength(); if(len > MAX_VELOCITY * MAX_VELOCITY) { len = sqrtf(len); newForce /= len; newForce *= MAX_VELOCITY; } newForce -= base; actor->actor->addVelocityChange(newForce); { QUAT rot; rotateToward(VC3(0, 1.f, 0), actor->force.GetNormalized(), rot); VC3 test(rot.x, rot.y, rot.z); test.x += ((float)(rand() - RAND_MAX/2) / (float)RAND_MAX/2); test.z += ((float)(rand() - RAND_MAX/2) / (float)RAND_MAX/2); if(test.GetSquareLength() > 0.001f) test.Normalize(); test *= 2.f; actor->actor->setAngularVelocity(test * 2.f); } actor->force = VC3(); } #endif actor->forceUpdate = false; } physics::resetFluidParticleCount(); for(FluidActorList::iterator it = data->fluidActorList.begin(); it != data->fluidActorList.end(); ++it) { PhysicsFluid *fluid = *it; if(!fluid->fluid) continue; if(fluid->addAmount) { fluid->fluid->addParticles(&fluid->buffer[0], fluid->addAmount); fluid->buffer.clear(); fluid->addAmount = 0; } fluid->fluid->setAcceleration(fluid->acceleration); fluid->fluid->update(); //fluid->renderFlag = false; } } /* // Meshes { for(MeshList::iterator it = data->meshList.begin(); it != data->meshList.end(); ++it) { MeshData &convex = *it; boost::shared_ptr<PhysicsMesh> mesh = convex.mesh.lock(); if(!mesh) continue; filesystem::FB_FILE *fp = filesystem::fb_fopen(convex.filename.c_str(), "rb"); if(!fp) { physics::Cooker cooker; cooker.cookApproxConvex(convex.filename.c_str(), convex.object); } else filesystem::fb_fclose(fp); mesh->mesh = data->physics->createConvexMesh(convex.filename.c_str()); } data->meshList.clear(); } */ // Actors { /* if(actorList.size() + physicsActorList.size() > MAX_ACTOR_AMOUNT) { boost::shared_ptr<PhysicsActor> nullActor; return nullActor; } */ bool sort = false; int createAmount = data->actorList.size(); if(createAmount > data->maxParticleSpawnAmount) { createAmount = data->maxParticleSpawnAmount; sort = true; } if(createAmount + data->createdActors > data->maxParticleAmount) { sort = true; createAmount = data->maxParticleAmount - data->createdActors; } if(sort) std::sort(data->actorList.begin(), data->actorList.end(), ActorListSorter()); // For collision test #ifdef PHYSX_SPAWN_TEST std::vector<BoxStruct> previousBoxes; #endif int index = 0; for(ActorList::iterator it = data->actorList.begin(); it != data->actorList.end(); ++it) { ActorData &convex = *it; if(convex.createDelayCounter++ >= MAX_WAIT_FOR_CREATE) continue; boost::shared_ptr<PhysicsActor> actor = convex.actor.lock(); if(!actor) continue; boost::shared_ptr<PhysicsMesh> mesh = convex.mesh.lock(); if(!mesh) continue; /* //VC3 boxCenter = mesh->localPosition + actor->position; VC3 boxCenter = mesh->localPosition; actor->rotation.RotateVector(boxCenter); boxCenter += actor->position; // Test to previous tick physics if(data->physics->checkOverlapOBB(boxCenter, mesh->size, actor->rotation, physics::PhysicsLib::CollisionStatic)) { convex.actor.reset(); convex.mesh.reset(); continue; } */ #ifdef PHYSX_SPAWN_TEST BoxStruct currentBox; currentBox.center.set(boxCenter.x, boxCenter.y, boxCenter.z); currentBox.extents.set(mesh->size.x, mesh->size.y, mesh->size.z); QUAT r = actor->rotation.GetInverse(); NxQuat quat; quat.setXYZW(r.x, r.y, r.z, r.w); currentBox.rotation.fromQuat(quat); // Test to previous tick physics if(data->physics->checkOverlapOBB(boxCenter, mesh->size, actor->rotation)) continue; bool hit = false; for(unsigned int i = 0; i < previousBoxes.size(); ++i) { const BoxStruct &b = previousBoxes[i]; if(NxBoxBoxIntersect(currentBox.extents, currentBox.center, currentBox.rotation, b.extents, b.center, b.rotation, true)) { hit = true; break; } } if(hit) continue; #endif // Don't create too many particles if(index++ >= createAmount) break; /* boost::shared_ptr<physics::ConvexActor> convexActor = data->physics->createConvexActor(mesh->mesh, actor->position); if(convexActor) { convexActor->setRotation(actor->rotation); convexActor->setVelocity(convex.velocity); convexActor->setAngularVelocity(convex.angularVelocity); convexActor->setMass(convex.mass); convexActor->setCollisionGroup(2); //convexActor->enableFeature(physics::ActorBase::DISABLE_GRAVITY, true); actor->actor = convexActor; } */ boost::shared_ptr<physics::BoxActor> boxActor = data->physics->createBoxActor(mesh->size, actor->position, mesh->localPosition); if(boxActor) { ++data->createdActors; boxActor->setRotation(actor->rotation); boxActor->setVelocity(convex.velocity); boxActor->setAngularVelocity(convex.angularVelocity); boxActor->setMass(convex.mass); boxActor->setCollisionGroup(convex.collisionGroup); #ifndef PHYSX_GRAVITY boxActor->enableFeature(physics::ActorBase::DISABLE_GRAVITY, true); #endif boxActor->setIntData(convex.soundGroup); actor->actor = boxActor; #ifdef PHYSX_SPAWN_TEST previousBoxes.push_back(currentBox); #endif } } int size = data->actorList.size(); for(int i = index; i < size; ++i) { data->actorList[i].createDelayCounter++; } if(index < size) { for(int i = 0; i < size - index; ++i) data->actorList[i] = data->actorList[i + index]; data->actorList.resize(size - index); } else data->actorList.clear(); } // Fluids { for(FluidList::iterator it = data->fluidList.begin(); it != data->fluidList.end(); ++it) { FluidData &fluidData = *it; boost::shared_ptr<PhysicsFluid> fluid = fluidData.fluid.lock(); if(!fluid) continue; boost::shared_ptr<physics::Fluid> fluidActor = data->physics->createFluid(physics::PhysicsLib::FluidType(fluidData.type), fluidData.maxParticles, fluidData.fluidStaticRestitution, fluidData.fluidStaticAdhesion, fluidData.fluidDynamicRestitution, fluidData.fluidDynamicAdhesion, fluidData.fluidDamping, fluidData.fluidStiffness, fluidData.fluidViscosity, fluidData.fluidKernelRadiusMultiplier, fluidData.fluidRestParticlesPerMeter, fluidData.fluidRestDensity, fluidData.fluidMotionLimit, fluidData.fluidPacketSizeMultiplier, fluidData.collisionGroup); fluid->fluid = fluidActor; fluid->lib = data; } data->fluidList.clear(); } }
void DebugTerrainObjectVisualizer::visualizeTerrainObject(game::Game *game, UnifiedHandle terrainObject, const VC3 &cameraPosition, DebugTerrainObjectVisFlags visFlags) { char textbuf[128]; assert(VALIDATE_UNIFIED_HANDLE_BITS(terrainObject)); if (!game->unifiedHandleManager->doesObjectExist(terrainObject)) { return; } VC3 cullpos = game->unifiedHandleManager->getObjectPosition(terrainObject); VC3 distToCamVec = cullpos - cameraPosition; // 2D RANGE distToCamVec.y = 0; float distToCamSq = distToCamVec.GetSquareLength(); if (distToCamSq < (DEBUGTERRAINOBJECTVISUALIZER_MAX_DIST * DEBUGTERRAINOBJECTVISUALIZER_MAX_DIST)) { // ok } else { return; } std::string fname = game->gameUI->getTerrain()->getTypeFilenameByUnifiedHandle(terrainObject); std::string fnamecut; for (int i = (int)fname.length() - 1; i >= 0; i--) { if (fname[i] == '\\') { fname[i] = '/'; } if (fname[i] == '/') { if (fnamecut.empty()) { fnamecut = fname.substr(i + 1, fname.length() - (i + 1)); } } } const char *totypename = game::SimpleOptions::getString(DH_OPT_S_DEBUG_VISUALIZE_TERRAINOBJECTS_OF_NAME); if (totypename != NULL && totypename[0] != '\0') { if (strstr(fname.c_str(), totypename) != NULL) { // ok } else { return; } } COL col = COL(0.5f,0.5f,1.0f); if (visFlags & DEBUGTERRAINOBJECTVISUALIZER_FLAG_SELECTED) { // ok with that color? } else { col.r = col.r / 2.0f; col.g = col.g / 2.0f; col.b = col.b / 2.0f; } /* VC3 pos = game->unifiedHandleManager->getObjectPosition(terrainObject); pos.y += 0.03f; VC3 sizes = VC3(1.00f, 1.00f, 1.00f); VC3 c1 = VC3(pos.x - sizes.x, pos.y + sizes.y, pos.z - sizes.z); VC3 c2 = VC3(pos.x + sizes.x, pos.y + sizes.y, pos.z - sizes.z); VC3 c3 = VC3(pos.x + sizes.x, pos.y + sizes.y, pos.z + sizes.z); VC3 c4 = VC3(pos.x - sizes.x, pos.y + sizes.y, pos.z + sizes.z); VC3 cb1 = VC3(pos.x - sizes.x, pos.y - sizes.y, pos.z - sizes.z); VC3 cb2 = VC3(pos.x + sizes.x, pos.y - sizes.y, pos.z - sizes.z); VC3 cb3 = VC3(pos.x + sizes.x, pos.y - sizes.y, pos.z + sizes.z); VC3 cb4 = VC3(pos.x - sizes.x, pos.y - sizes.y, pos.z + sizes.z); */ OOBB oobb = game->gameUI->getTerrain()->getOOBB(terrainObject); VC3 pos = oobb.center; VC3 c1 = pos - (oobb.axes[0] * oobb.extents.x) + (oobb.axes[1] * oobb.extents.y) - (oobb.axes[2] * oobb.extents.z); VC3 c2 = pos + (oobb.axes[0] * oobb.extents.x) + (oobb.axes[1] * oobb.extents.y) - (oobb.axes[2] * oobb.extents.z); VC3 c3 = pos + (oobb.axes[0] * oobb.extents.x) + (oobb.axes[1] * oobb.extents.y) + (oobb.axes[2] * oobb.extents.z); VC3 c4 = pos - (oobb.axes[0] * oobb.extents.x) + (oobb.axes[1] * oobb.extents.y) + (oobb.axes[2] * oobb.extents.z); VC3 cb1 = pos - (oobb.axes[0] * oobb.extents.x) - (oobb.axes[1] * oobb.extents.y) - (oobb.axes[2] * oobb.extents.z); VC3 cb2 = pos + (oobb.axes[0] * oobb.extents.x) - (oobb.axes[1] * oobb.extents.y) - (oobb.axes[2] * oobb.extents.z); VC3 cb3 = pos + (oobb.axes[0] * oobb.extents.x) - (oobb.axes[1] * oobb.extents.y) + (oobb.axes[2] * oobb.extents.z); VC3 cb4 = pos - (oobb.axes[0] * oobb.extents.x) - (oobb.axes[1] * oobb.extents.y) + (oobb.axes[2] * oobb.extents.z); /* VC3 pos = game->unifiedHandleManager->getObjectPosition(terrainObject); OOBB oobb = game->gameUI->getTerrain()->getOOBB(terrainObject); pos = oobb.center; VC3 sizes = oobb.extents; VC3 c1 = VC3(pos.x - sizes.x, pos.y + sizes.y, pos.z - sizes.z); VC3 c2 = VC3(pos.x + sizes.x, pos.y + sizes.y, pos.z - sizes.z); VC3 c3 = VC3(pos.x + sizes.x, pos.y + sizes.y, pos.z + sizes.z); VC3 c4 = VC3(pos.x - sizes.x, pos.y + sizes.y, pos.z + sizes.z); VC3 cb1 = VC3(pos.x - sizes.x, pos.y - sizes.y, pos.z - sizes.z); VC3 cb2 = VC3(pos.x + sizes.x, pos.y - sizes.y, pos.z - sizes.z); VC3 cb3 = VC3(pos.x + sizes.x, pos.y - sizes.y, pos.z + sizes.z); VC3 cb4 = VC3(pos.x - sizes.x, pos.y - sizes.y, pos.z + sizes.z); */ disposable_scene->AddLine(c1, c2, col); disposable_scene->AddLine(c2, c3, col); disposable_scene->AddLine(c3, c4, col); disposable_scene->AddLine(c4, c1, col); disposable_scene->AddLine(cb1, cb2, col); disposable_scene->AddLine(cb2, cb3, col); disposable_scene->AddLine(cb3, cb4, col); disposable_scene->AddLine(cb4, cb1, col); disposable_scene->AddLine(c1, cb1, col); disposable_scene->AddLine(c2, cb2, col); disposable_scene->AddLine(c3, cb3, col); disposable_scene->AddLine(c4, cb4, col); disposable_scene->AddLine(c4, cb4, col); int textoffy = 0; if (game::SimpleOptions::getBool(DH_OPT_B_DEBUG_VISUALIZE_TERRAINOBJECTS_EXTENDED) && distToCamSq < (DEBUGTERRAINOBJECTVISUALIZER_EXTENDED_MAX_DIST * DEBUGTERRAINOBJECTVISUALIZER_EXTENDED_MAX_DIST)) { sprintf(textbuf, "uh: %d", terrainObject); DebugVisualizerTextUtil::renderText(pos, 0, textoffy, textbuf); textoffy += 16; sprintf(textbuf, "filename: %s", fnamecut.c_str()); DebugVisualizerTextUtil::renderText(pos, 0, textoffy, textbuf); textoffy += 16; } }