void WifiStateMachine::triggerState(int state) { char buf[20]; char command[64]; snprintf(buf, sizeof(buf), "Entering state %d", state); Serial.println(buf); switch (state) { case WIFI_OFF: digitalWrite(resetPin, LOW); waitState(WIFI_RST_HIGH, 15 * MILLIS_PER_MINUTE); break; case WIFI_RST_HIGH: digitalWrite(resetPin, HIGH); waitState(WIFI_CIPSTART, 10 * MILLIS_PER_SECOND); break; case WIFI_CIPSTART: snprintf(command, sizeof(command), "AT+CIPSTART=\"UDP\",\"%s\",%d,%d,0", server, port, port); swSerial->println(command); waitState(WIFI_CIPSEND, 100); break; case WIFI_CIPSEND: payload = payloadCB(); snprintf(command, sizeof(command), "AT+CIPSEND=%d", strlen(payload) + 1); swSerial->println(command); waitState(WIFI_SEND_PAYLOAD, 100); break; case WIFI_SEND_PAYLOAD: swSerial->println(payload); waitState(WIFI_OFF, 10 * MILLIS_PER_SECOND); break; } }
void Timer::triggerState(int state) { switch (state) { case TIMER_STATE_IDLE: waitState(TIMER_STATE_FIRE, interval); break; case TIMER_STATE_FIRE: fire(); waitState(TIMER_STATE_IDLE, 0); break; } }
bool PathSitTask::Perform( Subsystem &subsystem ) { DM_LOG( LC_AI, LT_INFO )LOGSTRING( "PathSitTask performing.\r" ); idAI *owner = _owner.GetEntity(); // This task may not be performed with an empty owner pointer assert( owner != NULL ); // grayman #3670 - wait for the sitting down (and possibly turning // after) to finish, in case there's a target that needs to be activated idStr waitState( owner->WaitState() ); // grayman #3670 if( !_sittingAnimDone && ( ( waitState == "sit_down" ) || ( owner->AI_SIT_DOWN_ANGLE != owner->GetCurrentYaw() ) ) ) { return false; } if( !_sittingAnimDone ) { _sittingAnimDone = true; idPathCorner *path = _path.GetEntity(); // grayman #3670 // This task may not be performed with an empty path pointer assert( path != NULL ); path->ActivateTargets( owner ); } if( _waitEndTime >= 0 ) { if( gameLocal.time >= _waitEndTime ) { // Exit when the waitstate is not "get up" anymore //idStr waitState(owner->WaitState()); if( waitState != "get_up" ) { if( owner->GetMoveType() == MOVETYPE_SIT ) { owner->GetUp(); } else { return true; } } } } else { return true; } return false; }
bool PlayAnimationTask::Perform(Subsystem& subsystem) { DM_LOG(LC_AI, LT_INFO)LOGSTRING("PlayAnimationTask performing.\r"); idAI* owner = _owner.GetEntity(); // This task may not be performed with an empty owner pointer assert(owner != NULL); // Exit when the waitstate is not "customAnim" anymore idStr waitState(owner->WaitState()); if (waitState != "customAnim") { // We're finished, what now? if (_playCycle) { // Starte the anim cycle again StartAnim(owner); } else { return true; } } return false; }
Timer::Timer(unsigned long _interval, TimerCallback cb, void *ctx) { callback = cb; callbackContext = ctx; interval = _interval; waitState(TIMER_STATE_IDLE, 0); }
FUNCTION int Q4LI(obj user, obj usedon, int Q5NM) { int Q5NC = 0x00; if(Q50G(usedon)) { if(!getMobFlag(usedon, 0x02)) { int Q4NC; loc Q4VS = loc( getLocation(user) ); loc there = loc( getLocation(usedon) ); faceHere(user, getDirectionInternal(Q4VS, there)); if(hasObjVar(this, "magicItemModifier")) { Q4NC = 0x02 * (getObjVar(this, "magicItemModifier")) + 0x05; } else { Q4NC = (getSkillLevel(user, 0x19) / 0x0A + 0x01) * 0x02 + 0x05; } if(Q4CN(NULL(), usedon, 0x05)) { Q4NC = Q4NC / 0x02; } doMobAnimation(usedon, 0x376A, 0x06, Q4NC, 0x00, 0x00); sfx(there, 0x0204, 0x00); setWaitState(usedon, Q4NC); int Q67T = waitState(usedon); setMobFlag(usedon, 0x02, 0x01); scriptTrig(usedon, 0x01, user); if(isValid(usedon)) { Q422(user, usedon, 0x00, Q5NM); if(isValid(usedon)) { Q5UK(user, usedon, 0x02, Q5NM); if(isValid(usedon)) { attachScript(usedon, "rempara"); callback(usedon, Q4NC, 0x0D); } } } } } Q5UQ(this); return(Q5NC); }
void CGameEngine::initGame() { try{ boost::property_tree::ptree levelRoot; read_info("data\\test_level.info", levelRoot); CLevelLoader::load(levelRoot, m_level,m_resourceEngine); } catch(boost::property_tree::ptree_error &e){ CLog::error(e.what()); } m_level->setSpeed(100.0f); boost::shared_ptr<CPlayGameState> gameState(new CPlayGameState()); pushState(gameState); boost::shared_ptr<CWaitState> waitState(new CWaitState()); pushState(waitState); m_isRunning=true; }
bool PathSitTask::Perform(Subsystem& subsystem) { DM_LOG(LC_AI, LT_INFO)LOGSTRING("PathSitTask performing.\r"); idAI* owner = _owner.GetEntity(); // This task may not be performed with an empty owner pointer assert(owner != NULL); if (_waitEndTime >= 0) { if(gameLocal.time >= _waitEndTime) { // Exit when the waitstate is not "get up" anymore idStr waitState(owner->WaitState()); if (waitState != "get_up") { if (owner->GetMoveType() == MOVETYPE_SIT) { owner->GetUp(); } else { return true; } } } } else { return true; } return false; }
void WifiStateMachine::reset() { waitState(WIFI_OFF, 0); }
// Gets called each time the mind is thinking void UnreachableTargetState::Think(idAI* owner) { Memory& memory = owner->GetMemory(); idActor* enemy = _enemy.GetEntity(); if (enemy == NULL) { DM_LOG(LC_AI, LT_ERROR)LOGSTRING("No enemy!\r"); owner->GetMind()->SwitchState(STATE_LOST_TRACK_OF_ENEMY); return; } // grayman #3492 - if you kill the enemy with a rock, behave the same // way you would had you killed him with a weapon if (enemy->AI_DEAD) { owner->SetLastKilled(enemy); owner->ClearEnemy(); owner->StopMove(MOVE_STATUS_DONE); owner->SetAlertLevel(owner->thresh_2 + (owner->thresh_3 - owner->thresh_2) * 0.5); // grayman #3473 - stop looking at the spot you were looking at when you killed the enemy owner->SetFocusTime(gameLocal.time); // bark about death idStr bark = ""; idStr enemyAiUse = enemy->spawnArgs.GetString("AIUse"); if ( ( enemyAiUse == AIUSE_MONSTER ) || ( enemyAiUse == AIUSE_UNDEAD ) ) { bark = "snd_killed_monster"; } else { bark = "snd_killed_enemy"; } owner->PostEventMS(&AI_Bark,ENEMY_DEAD_BARK_DELAY,bark); owner->GetMind()->EndState(); return; } // Check the distance to the enemy, the other subsystem tasks need it. memory.canHitEnemy = owner->CanHitEntity(enemy); if (!owner->AI_ENEMY_VISIBLE) { // The enemy is not visible, let's keep track of him for a small amount of time if (gameLocal.time - memory.lastTimeEnemySeen < MAX_BLIND_CHASE_TIME) { // Cheat a bit and take the last reachable position as "visible & reachable" owner->lastVisibleReachableEnemyPos = owner->lastReachableEnemyPos; } else { // BLIND_CHASE_TIME has expired, we have lost the enemy! owner->GetMind()->SwitchState(STATE_LOST_TRACK_OF_ENEMY); return; } } owner->TurnToward(enemy->GetPhysics()->GetOrigin()); if (owner->spawnArgs.GetBool("outofreach_projectile_enabled", "0") && _moveRequired && (owner->AI_MOVE_DONE || owner->AI_DEST_UNREACHABLE)) { // We are finished moving closer // Start throwing now _moveRequired = false; // greebo: Sheathe weapon before starting to throw // FIXME: put weapon to left hand? owner->SheathWeapon(); owner->FaceEnemy(); owner->actionSubsystem->PushTask(ThrowObjectTask::CreateInstance()); _takeCoverTime = gameLocal.time + 3000; } // This checks if the enemy is reachable again so we can go into combat state if (owner->enemyReachable || owner->TestMelee() || memory.canHitEnemy) { if (owner->GetMind()->PerformCombatCheck()) { owner->GetMind()->EndState(); return; } } // This checks for a reachable position within combat range idVec3 enemyDirection = owner->GetPhysics()->GetOrigin() - enemy->GetPhysics()->GetOrigin(); enemyDirection.z = 0; enemyDirection.NormalizeFast(); float angle = (_reachEnemyCheck * 90) % 360; float sinAngle = idMath::Sin(angle); float cosAngle = idMath::Cos(angle); idVec3 targetDirection = enemyDirection; targetDirection.x = enemyDirection.x * cosAngle + enemyDirection.y * sinAngle; targetDirection.y = enemyDirection.y * cosAngle + enemyDirection.x * sinAngle; idVec3 targetPoint = enemy->GetPhysics()->GetOrigin() + (targetDirection * owner->melee_range); idVec3 bottomPoint = targetPoint; bottomPoint.z -= 70; trace_t result; if (gameLocal.clip.TracePoint(result, targetPoint, bottomPoint, MASK_OPAQUE, NULL)) { targetPoint.z = result.endpos.z + 1; int areaNum = owner->PointReachableAreaNum(owner->GetPhysics()->GetOrigin(), 1.0f); idVec3 forward = owner->viewAxis.ToAngles().ToForward(); int targetAreaNum = owner->PointReachableAreaNum(targetPoint, 1.0f, -10*forward); aasPath_t path; if (owner->PathToGoal(path, areaNum, owner->GetPhysics()->GetOrigin(), targetAreaNum, targetPoint, owner)) { owner->GetMind()->EndState(); return; } else { _reachEnemyCheck++; } } else { _reachEnemyCheck++; } _reachEnemyCheck %= 4; // Wait at least for 3 seconds (_takeCoverTime) after starting to throw before taking cover // If a ranged threat from the player is detected (bow is out) // take cover if possible after throwing animation is finished idStr waitState(owner->WaitState()); if ( _takingCoverPossible && ( waitState != "throw" ) && ( _takeCoverTime > 0 ) && ( gameLocal.time > _takeCoverTime ) && ( enemy->RangedThreatTo(owner) || !owner->spawnArgs.GetBool("taking_cover_only_from_archers","0") )) { owner->GetMind()->SwitchState(STATE_TAKE_COVER); } }
void MeleeCombatTask::PerformParry(idAI* owner) { CMeleeStatus& ownerStatus = owner->m_MeleeStatus; CMeleeStatus& enemyStatus = _enemy.GetEntity()->m_MeleeStatus; EMeleeActPhase phase = ownerStatus.m_ActionPhase; if ( phase == MELEEPHASE_PREPARING ) { if( cv_melee_state_debug.GetBool() ) { idStr debugText = "MeleeAction: Parry, Phase: Preparing"; gameRenderWorld->DrawText( debugText, (owner->GetEyePosition() - owner->GetPhysics()->GetGravityNormal()*-25), 0.20f, colorMagenta, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1, gameLocal.msec ); } // wait until done with initial delay, then start the animation if ( _bInPreParryDelayState && ((gameLocal.time - _ParryDelayTimer) > _PreParryDelay) ) { // Set the waitstate, this gets cleared by script when the anim is done owner->SetWaitState("melee_action"); const char *suffix = idActor::MeleeTypeNames[ownerStatus.m_ActionType]; // script state plays the animation and clears wait state when done // TODO: Why did we have 5 blend frames here? owner->SetAnimState(ANIMCHANNEL_TORSO, va("Torso_Parry_%s",suffix), 5); _bInPreParryDelayState = false; } // don't do anything, animation will update status when it reaches hold point return; } if ( phase == MELEEPHASE_HOLDING ) { if( cv_melee_state_debug.GetBool() ) { idStr debugText = "MeleeAction: Parry, Phase: Holding"; gameRenderWorld->DrawText( debugText, (owner->GetEyePosition() - owner->GetPhysics()->GetGravityNormal()*-25), 0.20f, colorMagenta, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1, gameLocal.msec ); } // Decide whether to keep holding the parry or to release bool bRelease = false; // If our enemy is no longer attacking, release if( enemyStatus.m_ActionState != MELEEACTION_ATTACK || enemyStatus.m_ActionPhase == MELEEPHASE_RECOVERING ) bRelease = true; // If our enemy switches attacks, stop this parry to prepare the next else if( ownerStatus.m_ActionType != MELEETYPE_BLOCKALL && ownerStatus.m_ActionType != enemyStatus.m_ActionType ) bRelease = true; // or if enemy is holding for over some time else if( enemyStatus.m_ActionPhase == MELEEPHASE_HOLDING && ((gameLocal.time - enemyStatus.m_PhaseChangeTime) > owner->m_MeleeCurrentParryHold) ) { // also force an attack next, so we don't just go back into parry - this creates an opening _bForceAttack = true; bRelease = true; } // TODO: Check if enemy is dead or beyond some max range, then stop parrying? else { // debug display the countdown to release if( cv_melee_state_debug.GetBool() ) { idStr debugText = va("Parry Waiting for: %d [ms]", (gameLocal.time - enemyStatus.m_PhaseChangeTime) ); gameRenderWorld->DrawText( debugText, (owner->GetEyePosition() - owner->GetPhysics()->GetGravityNormal()*-40), 0.20f, colorMagenta, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1, gameLocal.msec ); } // otherwise, keep holding the parry bRelease = false; } if( bRelease ) { // owner->Event_PauseAnim( ANIMCHANNEL_TORSO, false ); _bInPostParryDelayState = true; _ParryDelayTimer = gameLocal.time; owner->Event_MeleeActionReleased(); } } // MELEEPHASE_RECOVERING else { // recovery has two phases: 1. Wait for post-parry delay reaction time // and 2. wait for recovery animation to finish // If just finishing up the initial delay, start the animation if( _bInPostParryDelayState && ((gameLocal.time - _ParryDelayTimer) > _PostParryDelay) ) { owner->Event_PauseAnim( ANIMCHANNEL_TORSO, false ); _bInPostParryDelayState = false; } // post parry delay has already finished, wait for animation else if( !_bInPostParryDelayState ) { // check if animation is finished (script will set this when it is) idStr waitState( owner->WaitState() ); if( waitState != "melee_action" ) { // if nothing happened with our parry, it was aborted if( ownerStatus.m_ActionResult == MELEERESULT_IN_PROGRESS ) ownerStatus.m_ActionResult = MELEERESULT_PAR_ABORTED; owner->Event_MeleeActionFinished(); } } // otherwise we wait for the post parry delay if( cv_melee_state_debug.GetBool() ) { idStr debugText = "MeleeAction: Parry, Phase: Recovering"; gameRenderWorld->DrawText( debugText, (owner->GetEyePosition() - owner->GetPhysics()->GetGravityNormal()*-25), 0.20f, colorMagenta, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1, gameLocal.msec ); } } }
void MeleeCombatTask::PerformAttack(idAI* owner) { CMeleeStatus& ownerStatus = owner->m_MeleeStatus; EMeleeActPhase phase = ownerStatus.m_ActionPhase; Memory& memory = owner->GetMemory(); if( phase == MELEEPHASE_PREPARING ) { if( cv_melee_state_debug.GetBool() ) { idStr debugText = "MeleeAction: Attack, Phase: Preparing"; gameRenderWorld->DrawText( debugText, (owner->GetEyePosition() - owner->GetPhysics()->GetGravityNormal()*-25), 0.20f, colorMagenta, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1, gameLocal.msec ); } // don't do anything, animation will update melee status to holding when it reaches the hold point // FIX: Some animations don't have a hold point and just go straight through idStr waitState( owner->WaitState() ); if( waitState != "melee_action" ) { // Hack: animation is done, advance the state where it will be handled properly in the next frame owner->Event_MeleeActionReleased(); } return; } else if( phase == MELEEPHASE_HOLDING ) { // TODO: Decide whether to keep holding the attack or release // if player is out of range but close, maybe hold the swing and charge at them for a little while? if( cv_melee_state_debug.GetBool() ) { idStr debugText = "MeleeAction: Attack, Phase: Holding"; gameRenderWorld->DrawText( debugText, (owner->GetEyePosition() - owner->GetPhysics()->GetGravityNormal()*-25), 0.20f, colorMagenta, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1, gameLocal.msec ); } // wait some finite time before releasing (for difficulty tweaking) if( (gameLocal.time - ownerStatus.m_PhaseChangeTime) > owner->m_MeleeCurrentHoldTime ) { owner->Event_PauseAnim( ANIMCHANNEL_TORSO, false ); owner->Event_MeleeActionReleased(); } } // MELEEPHASE_EXECUTING OR MELEEPHASE_RECOVERING else { if( cv_melee_state_debug.GetBool() ) { idStr debugText = "MeleeAction: Attack, Phase: Executing/Recovering"; gameRenderWorld->DrawText( debugText, (owner->GetEyePosition() - owner->GetPhysics()->GetGravityNormal()*-25), 0.20f, colorMagenta, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1, gameLocal.msec ); } // check if animation is finished (script will set this when it is) idStr waitState( owner->WaitState() ); if( waitState != "melee_action" ) { // if attack hasn't hit anything, switch to missed at this point if (ownerStatus.m_ActionResult == MELEERESULT_IN_PROGRESS) { ownerStatus.m_ActionResult = MELEERESULT_AT_MISSED; } else if (ownerStatus.m_ActionResult == MELEERESULT_AT_PARRIED) { // Emit our frustration bark with a certain probability (1 out of 3) if (gameLocal.random.RandomFloat() > 0.7f) { EmitCombatBark(owner, "snd_combat_blocked_by_player"); } } else if (ownerStatus.m_ActionResult == MELEERESULT_AT_HIT) { // Emit our success bark with a certain probability (1 out of 3) if (gameLocal.random.RandomFloat() > 0.7f) { bool hasCompany = (MS2SEC(gameLocal.time - memory.lastTimeFriendlyAISeen) <= MAX_FRIEND_SIGHTING_SECONDS_FOR_ACCOMPANIED_ALERT_BARK); EmitCombatBark(owner, hasCompany ? "snd_combat_hit_player_company" : "snd_combat_hit_player"); } } owner->Event_MeleeActionFinished(); } } }