dTileModel dMap::getVisibleTileModel(int x, int y) { if(getNPC(x,y)) return getNPC(x,y)->getModel(); if(getItem(x,y)) return getItem(x,y)->getModel(); if(!mMap[x][y]) return dTileModel(); return mMap[x][y]->getModel(); }
void NPCCameraman_DZ::onUpdate(float dt) { //getCore()->logMessage("NPCCameraman_DZ::onUpdate"); // follow cat toy untile it is roaming if( false && getNPC()->getJumper()->getPhase() == ::jpRoaming ) { getCore()->logMessage("call NPCFollow"); call( new NPCFollow( getNPC(), 100.0f ) ); } // frefall for cat toy until it is in freefall else if( getNPC()->getJumper()->getPhase() == ::jpRoaming || getNPC()->getJumper()->getPhase() == ::jpFreeFalling ) { //getCore()->logMessage("call NPCFreefall_DZ"); call( new NPCFreefall_DZ( getNPC() ) ); } // flight for cat toy else { getCore()->logMessage("call NPCFlight_DZ"); bool canopyIsSkydiving = database::Canopy::getRecord( getNPC()->getJumper()->getVirtues()->equipment.canopy.id )->skydiving; if( canopyIsSkydiving ) { call( new NPCFlight_DZ( getNPC(), 75.0f, 50.0f ) ); } else { call( new NPCFlight_DZ( getNPC(), 25.0f, 7.5f ) ); } } }
void NPCCameraman::onUpdate(float dt) { // follow cat toy untile it is roaming if( getNPC()->getCatToy()->getPhase() == ::jpRoaming ) { call( new NPCFollow( getNPC(), 100.0f ) ); } // frefall for cat toy until it is in freefall else if( getNPC()->getCatToy()->getPhase() == ::jpFreeFalling ) { call( new NPCFreefall( getNPC() ) ); } // flight for cat toy else { bool canopyIsSkydiving = database::Canopy::getRecord( getNPC()->getJumper()->getVirtues()->equipment.canopy.id )->skydiving; if( canopyIsSkydiving ) { call( new NPCFlight( getNPC(), 75.0f, 50.0f ) ); } else { call( new NPCFlight( getNPC(), 25.0f, 7.5f ) ); } } }
void NPCAssist::onUpdate(float dt) { // follow cat toy until it is roaming if( getNPC()->getCatToy()->getPhase() == ::jpRoaming ) { call( new NPCFollow( getNPC(), 75.0f ) ); } // pull and drop ward's pilotchute else if( _ward && !_ward->getFreefallActor()->isSleeping() ) { // pilotchute pull frame Vector3f pp = Jumper::getLineHandJoint( getNPC()->getJumper()->getClump() )->getPos(); Vector3f py = _ward->getClump()->getFrame()->getPos() - getNPC()->getJumper()->getClump()->getFrame()->getPos(); py.normalize(); Vector3f px; px.cross( py, Vector3f(0,1,0) ); px.normalize(); Vector3f pz; py.cross( px, py ); pz.normalize(); // check wind float windSpeed = 0.5f * ( getNPC()->getScene()->getLocation()->getWindAmbient() + getNPC()->getScene()->getLocation()->getWindBlast() ); Vector3f wardAt = _ward->getClump()->getFrame()->getAt(); wardAt.normalize(); if( windSpeed < 2.0f || Vector3f::dot( wardAt, getNPC()->getScene()->getLocation()->getWindDirection() ) < 0 ) { // connect pilot chute _ward->getPilotchuteSimulator()->connect( _ward->getFreefallActor(), Jumper::getBackBone( _ward->getClump() ), _ward->getLocalPilotAnchor() ); // pull pilotchute _ward->getPilotchuteSimulator()->pull( Matrix4f( px[0], px[1], px[2], 0.0f, py[0], py[1], py[2], 0.0f, pz[0], pz[1], pz[2], 0.0f, pp[0], pp[1], pp[2], 1.0f ) ); _ward->getPilotchuteSimulator()->updateActivity( 0.0f ); // and drop _ward->getPilotchuteSimulator()->drop( NxVec3( 0,0,0 ) ); _ward->getPilotchuteSimulator()->setInflation( 0.25f ); } // and no longer track the ward happiness :) _ward = NULL; } }
bool NPCFreefall_DZ::isEndOfProgram(void) { return getNPC()->getJumper()->getPhase() == ::jpFlight; }
void NPCFreefall_DZ::onUpdate(float dt) { // obtain spinal cord SpinalCord* spinalCord = getNPC()->getSpinalCord(); spinalCord->reset(); // update target position Matrix4f catToyPose = getNPC()->getCatToy()->getCurrentPose(); _targetPos.set( catToyPose[3][0], catToyPose[3][1], catToyPose[3][2] ); // jump only when the wind is right Vector2f pos = Vector2f(catToyPose[3][0], catToyPose[3][2]); pos.normalize(); NxVec3 wind = getNPC()->getJumper()->getScene()->getWindAtPoint(NxVec3(catToyPose[3][0], catToyPose[3][1], catToyPose[3][2])); wind.normalize(); Vector2f wind2(wind.x, wind.z); float wind_angle = 0.0; if (wind.magnitude() < 1.5f) { wind_angle = 1.0f; } else { wind2.normalize(); wind_angle = pos.dot(wind2); } // if my character is still roaming if (wind_angle >= 0.8f && catToyPose[3][1] >= 300.0f) _timeUntilJump -= dt; //getCore()->logMessage("%s has %2.4f seconds to jump", getNPC()->getNPCName(), _timeUntilJump); if( _timeUntilJump <= 0.0f && getNPC()->getJumper()->getPhase() == ::jpRoaming ) { Vector3f pos = Vector3f(catToyPose[3][0], catToyPose[3][1], catToyPose[3][2]); // if npc on airplane if( getNPC()->getJumper()->getAirplane() != NULL ) { // just jump! spinalCord->phase = true; return; } // if npc at the exit point and ready to jump else if( _positionIsSucceed && _directionIsSucceed ) { // jump! spinalCord->phase = true; return; } // if npc at the exit point and not surely ready to clear jump else { if( !_positionIsSucceed ) { // move to abyss Matrix4f jumpPose = getNPC()->getCatToy()->getJumpPose(); Vector3f jumpPos( jumpPose[3][0], jumpPose[3][1], jumpPose[3][2] ); call( new NPCMove( getNPC(), jumpPos ) ); _positionIsSucceed = true; return; } if( !_directionIsSucceed ) { // jumper absolute orientation Vector3f jumperAt = getNPC()->getJumper()->getClump()->getFrame()->getAt(); jumperAt.normalize(); // direction of cat toy jump Matrix4f jumpPose = getNPC()->getCatToy()->getJumpPose(); Vector3f targetDir( jumpPose[2][0], 0.0f, jumpPose[2][2] ); targetDir.normalize(); // angle to target Vector3f atH = jumperAt; atH[1] = 0; atH.normalize(); Vector3f dirH = targetDir; dirH[1] = 0; dirH.normalize(); float targetAngle = ::calcAngle( dirH, atH, Vector3f( 0,1,0 ) ); if( fabs( targetAngle ) < 1.0f ) { _directionIsSucceed = true; return; } else { // turn jumper by AI algo float aiRotationVel = 180.0f; float aiRotationAngle = sgn( targetAngle ) * aiRotationVel * dt; if( fabs( aiRotationAngle ) > fabs( targetAngle ) ) aiRotationAngle = targetAngle; getNPC()->getJumper()->getClump()->getFrame()->rotateRelative( Vector3f( 0,1,0 ), aiRotationAngle ); } } } } // else, turn & track towards the target else if( getNPC()->getJumper()->getPhase() == ::jpFreeFalling ) { // jumper absolute orientation Vector3f jumperAt = getNPC()->getJumper()->getClump()->getFrame()->getAt(); jumperAt.normalize(); Vector3f jumperRight = getNPC()->getJumper()->getClump()->getFrame()->getRight(); jumperRight.normalize(); Vector3f jumperUp = getNPC()->getJumper()->getClump()->getFrame()->getUp(); jumperUp.normalize(); // retrieve current jumper position Vector3f jumperPos = getNPC()->getJumper()->getClump()->getFrame()->getPos(); jumperPos += Vector3f( 0, jumperRoamingSphereSize, 0 ); // wingsuit bool wingsuit = database::Suit::getRecord(getNPC()->getJumper()->getVirtues()->equipment.suit.id)->wingsuit; // leveling // wlo - when npc higher //if (!wingsuit) { // if (jumperPos[1] - _targetPos[1] > 1500.0f) { // spinalCord->wlo = true; // } else if (jumperPos[1] - _targetPos[1] < -1500.0f) { // spinalCord->hook = true; // } //} // direction to target Vector3f targetDir = _targetPos - jumperPos; float distanceToTarget = Vector3f( targetDir[0], 0, targetDir[2] ).length(); targetDir.normalize(); // landing too far away? let's deploy in order to return safely // glide ratio is based on canopy size database::Canopy *canopy = database::Canopy::getRecord(getNPC()->getJumper()->getVirtues()->equipment.canopy.id); Vector3f pos = getNPC()->getJumper()->getClump()->getFrame()->getPos(); float glide = canopy->square / 150.0f; float alt = pos[1]; pos[1] = 0; bool farEnough = pos.length() >= alt*glide; //getCore()->logMessage("alt: %2.5f; dst: %2.5f; coverage: %2.5f", alt, pos.length(), alt*glide); // deploy now? if ((alt <= 85000.0f || farEnough) && alt <= 150000.0f) { if (getNPC()->getJumper()->getCanopySimulator()) { //getCore()->logMessage("npc pull. Far enough: %d", (int)farEnough); spinalCord->phase = true; spinalCord->modifier = wingsuit; } else { //getCore()->logMessage("npc pull reserve. Far enough: %d", (int)farEnough); spinalCord->pullReserve = true; spinalCord->modifier = wingsuit; } } // if toy tracking modifier is on if( wingsuit /* getNPC()->getCatToy()->getModifier()*/ ) { // sum up target direction Vector3f targetFlatAt( getNPC()->getCatToy()->getCurrentPose()[2][0], 0, getNPC()->getCatToy()->getCurrentPose()[2][2] ); /*getCore()->logMessage( "POS: %3.2f %3.2f %3.2f AT : %3.2f 0.0 %3.2f", getNPC()->getCatToy()->getCurrentPose()[3][0], getNPC()->getCatToy()->getCurrentPose()[3][1], getNPC()->getCatToy()->getCurrentPose()[3][2], targetFlatAt[0], targetFlatAt[2] );*/ targetFlatAt.normalize(); targetDir += targetFlatAt * 3; targetDir.normalize(); } // horizontal steering float minAngle = 5.0f; float minValue = 0.0f; float maxAngle = 45.0f; float maxValue = 1.0f; // angle to target Vector3f atH = jumperAt; // headdown if (getNPC()->getJumper()->getDefaultPose() == 1) { atH = jumperUp; minAngle = 25.0f; maxValue = 0.1f; // sitfly } else if (getNPC()->getJumper()->getDefaultPose() == 2) { atH = jumperUp; atH[2] *= -1; //minAngle = 25.0f; maxValue = 0.1f; } atH[1] = 0; atH.normalize(); Vector3f dirH = targetDir; dirH[1] = 0; dirH.normalize(); float targetAngle = ::calcAngle( dirH, atH, Vector3f( 0,1,0 ) ); // inclination angle relative to the horizont float horizontalAngle = -1 * ::calcAngle( atH, jumperUp, jumperRight ); // horizontal steering float factor = ( fabs( targetAngle ) - minAngle ) / ( maxAngle - minAngle ); factor = ( factor < 0 ) ? 0 : ( ( factor > 1 ) ? 1 : factor ); float impulse = minValue * ( 1 - factor ) + maxValue * factor; if (wingsuit) impulse = 0.0f; // smooth impulse impulse = pow( impulse, 1.25f ); if (alt <= 130000.0f) impulse = 0.0f; // apply impulse if( targetAngle < 0 ) { spinalCord->right = impulse; } else { spinalCord->left = impulse; } // relation btw desired inclination and target angle minAngle = 5.0f; minValue = 25.0f; maxAngle = 90.0f; maxValue = 0.0f; factor = ( fabs( targetAngle ) - minAngle ) / ( maxAngle - minAngle ); factor = ( factor < 0 ) ? 0 : ( ( factor > 1 ) ? 1 : factor ); float desiredInclination = minValue * ( 1 - factor ) + maxValue * factor; // inclination difference float inclinationDifference = desiredInclination - horizontalAngle; // vertical steering minAngle = 0.0f; minValue = 0.0f; maxAngle = 30.0f; maxValue = 1.0f; factor = ( fabs( inclinationDifference ) - minAngle ) / ( maxAngle - minAngle ); factor = ( factor < 0 ) ? 0 : ( ( factor > 1 ) ? 1 : factor ); impulse = minValue * ( 1 - factor ) + maxValue * factor; if (!wingsuit && distanceToTarget > 2500.0f && alt > 130000.0f) { if( inclinationDifference < 0 ) { spinalCord->down += impulse; if (spinalCord->down > 1.0f) spinalCord->down = 1.0f; } else { spinalCord->up += impulse; if (spinalCord->up > 1.0f) spinalCord->up = 1.0f; } } // tracking modifier if( fabs( targetAngle ) < 90.0f && distanceToTarget > 2500.0f ) { spinalCord->modifier = 0.0f; spinalCord->trigger_modifier = false; } else { spinalCord->modifier = 0.0f; spinalCord->trigger_modifier = false; } if (wingsuit || alt <= 130000.0f) spinalCord->modifier = 1.0f; if (wingsuit || alt <= 130000.0f) spinalCord->trigger_modifier = true; return; // force tracking in several condition if( getNPC()->getCatToy()->getModifier() ) { // not a skydiving? if( !getNPC()->getJumper()->getCanopySimulator()->getGearRecord()->skydiving ) { // imitate cat toy modifier spinalCord->modifier = getNPC()->getCatToy()->getModifier(); } else { Vector3f cattoyFaceH( catToyPose[2][0], 0, catToyPose[2][2] ); cattoyFaceH.normalize(); Vector3f npcFaceH = getNPC()->getJumper()->getClump()->getFrame()->getAt(); npcFaceH[1] = 0; npcFaceH.normalize(); //if( Vector3f::dot( dirH, cattoyFaceH ) > 0.85f ) spinalCord->modifier = true; } } } }