void TBackend::SaveState(void) { pSaveToken = pToken; saveToken = token; pSaveIcode = pIcode; pSaveNode = pNode; saveLocation = CurrentLocation(); saveLineNumber = currentLineNumber; pSaveTokenString = new char[strlen(pToken->String()) + 1]; strcpy(pSaveTokenString, pToken->String()); }
/* ------------------------- NPC_BSAnimal_Default ------------------------- */ void NPC_BSAnimal_Default( void ) { if (!NPC || !NPC->client) { return; } // Update Some Positions //----------------------- CVec3 CurrentLocation(NPC->currentOrigin); // Update The Leader //------------------- gentity_t* leader = NPC_AnimalUpdateLeader(); // Select Closest Threat Location //-------------------------------- CVec3 ThreatLocation(0,0,0); qboolean PlayerSpawned = G_PlayerSpawned(); if ( PlayerSpawned ) {//player is actually in the level now ThreatLocation = player->currentOrigin; } int alertEvent = NPC_CheckAlertEvents(qtrue, qtrue, -1, qfalse, AEL_MINOR, qfalse); if ( alertEvent >= 0 ) { alertEvent_t *event = &level.alertEvents[alertEvent]; if (event->owner!=NPC && Distance(event->position, CurrentLocation.v)<event->radius) { ThreatLocation = event->position; } } // float DistToThreat = CurrentLocation.Dist(ThreatLocation); // float DistFromHome = CurrentLocation.Dist(mHome); bool EvadeThreat = (level.time<NPCInfo->investigateSoundDebounceTime); bool CharmedDocile = (level.time<NPCInfo->confusionTime); bool CharmedApproach = (level.time<NPCInfo->charmedTime); // If Not Already Evading, Test To See If We Should "Know" About The Threat //-------------------------------------------------------------------------- /* if (false && !EvadeThreat && PlayerSpawned && (DistToThreat<FRIGHTEN_DISTANCE)) { CVec3 LookAim(NPC->currentAngles); LookAim.AngToVec(); CVec3 MyPos(CurrentLocation); MyPos -= ThreatLocation; MyPos.SafeNorm(); float DirectionSimilarity = MyPos.Dot(LookAim); if (fabsf(DirectionSimilarity)<0.8f) { EvadeThreat = true; NPCInfo->investigateSoundDebounceTime = level.time + Q_irand(0, 1000); VectorCopy(ThreatLocation.v, NPCInfo->investigateGoal); } }*/ STEER::Activate(NPC); { // Charmed Approach - Walk TOWARD The Threat Location //---------------------------------------------------- if (CharmedApproach) { NAV::GoTo(NPC, NPCInfo->investigateGoal); } // Charmed Docile - Stay Put //--------------------------- else if (CharmedDocile) { NAV::ClearPath(NPC); STEER::Stop(NPC); } // Run Away From This Threat //--------------------------- else if (EvadeThreat) { NAV::ClearPath(NPC); STEER::Flee(NPC, NPCInfo->investigateGoal); } // Normal Behavior //----------------- else { // Follow Our Pack Leader! //------------------------- if (leader && leader!=NPC) { float followDist = 100.0f; float curDist = Distance(NPC->currentOrigin, leader->followPos); // Update The Leader's Follow Position //------------------------------------- STEER::FollowLeader(NPC, leader, followDist); bool inSeekRange = (curDist<followDist*10.0f); bool onNbrPoints = (NAV::OnNeighboringPoints(NAV::GetNearestNode(NPC), leader->followPosWaypoint)); bool leaderStop = ((level.time - leader->lastMoveTime)>500); // If Close Enough, Dump Any Existing Path //----------------------------------------- if (inSeekRange || onNbrPoints) { NAV::ClearPath(NPC); // If The Leader Isn't Moving, Stop //---------------------------------- if (leaderStop) { STEER::Stop(NPC); } // Otherwise, Try To Get To The Follow Position //---------------------------------------------- else { STEER::Seek(NPC, leader->followPos, fabsf(followDist)/2.0f/*slowing distance*/, 1.0f/*wight*/, leader->resultspeed); } } // Otherwise, Get A Path To The Follow Position //---------------------------------------------- else { NAV::GoTo(NPC, leader->followPosWaypoint); } STEER::Separation(NPC, 4.0f); STEER::AvoidCollisions(NPC, leader); } // Leader AI - Basically Wander //------------------------------ else { // Are We Doing A Path? //---------------------- bool HasPath = NAV::HasPath(NPC); if (HasPath) { HasPath = NAV::UpdatePath(NPC); if (HasPath) { STEER::Path(NPC); // Follow The Path STEER::AvoidCollisions(NPC); } } if (!HasPath) { // If Debounce Time Has Expired, Choose A New Sub State //------------------------------------------------------ if (NPCInfo->investigateDebounceTime<level.time) { // Clear Out Flags From The Previous Substate //-------------------------------------------- NPCInfo->aiFlags &= ~NPCAI_OFF_PATH; NPCInfo->aiFlags &= ~NPCAI_WALKING; // Pick Another Spot //------------------- int NEXTSUBSTATE = Q_irand(0, 10); bool RandomPathNode = (NEXTSUBSTATE<8); //(NEXTSUBSTATE<9); bool PathlessWander = (NEXTSUBSTATE<9); //false; // Random Path Node //------------------ if (RandomPathNode) { // Sometimes, Walk //----------------- if (Q_irand(0, 1)==0) { NPCInfo->aiFlags |= NPCAI_WALKING; } NPCInfo->investigateDebounceTime = level.time + Q_irand(3000, 10000); NAV::FindPath(NPC, NAV::ChooseRandomNeighbor(NAV::GetNearestNode(NPC)));//, mHome.v, WANDER_RANGE)); } // Pathless Wandering //-------------------- else if (PathlessWander) { // Sometimes, Walk //----------------- if (Q_irand(0, 1)==0) { NPCInfo->aiFlags |= NPCAI_WALKING; } NPCInfo->investigateDebounceTime = level.time + Q_irand(3000, 10000); NPCInfo->aiFlags |= NPCAI_OFF_PATH; } // Just Stand Here //----------------- else { NPCInfo->investigateDebounceTime = level.time + Q_irand(2000, 6000); //NPC_SetAnim(NPC, SETANIM_BOTH, ((Q_irand(0, 1)==0)?(BOTH_GUARD_LOOKAROUND1):(BOTH_GUARD_IDLE1)), SETANIM_FLAG_NORMAL); } } // Ok, So We Don't Have A Path, And Debounce Time Is Still Active, So We Are Either Wandering Or Looking Around //-------------------------------------------------------------------------------------------------------------- else { // if (DistFromHome>(WANDER_RANGE)) // { // STEER::Seek(NPC, mHome); // } // else { if (NPCInfo->aiFlags & NPCAI_OFF_PATH) { STEER::Wander(NPC); STEER::AvoidCollisions(NPC); } else { STEER::Stop(NPC); } } } } } } } STEER::DeActivate(NPC, &ucmd); NPC_UpdateAngles( qtrue, qtrue ); }