void CAIWeaponAbstract::Load(ILTMessage_Read *pMsg) { HOBJECT hOwner = NULL; HWEAPON hWeapon = NULL; LOAD_HOBJECT(hOwner); LOAD_HRECORD( hWeapon, g_pWeaponDB->GetWeaponsCategory() ); LOAD_STDSTRING(m_szFireSocketName); LOAD_INT_CAST(m_eFiringState, ENUM_AIFiringState); LOAD_DWORD(m_iAnimRandomSeed); LOAD_TIME(m_fRandomSeedSelectionTime); LOAD_FLOAT(m_flWeaponContextInaccuracyScalar); LOAD_DWORD(m_hWeaponSocket); LOAD_bool(m_bCanDropWeapon); ASSERT(IsAI(hOwner)); CAI* pAI = (CAI*)g_pLTServer->HandleToObject(hOwner); ASSERT(pAI->GetArsenal()); if (pAI) { ASSERT(pAI->GetArsenal()); if (CArsenal* pArsenal = pAI->GetArsenal()) { m_pWeapon = pArsenal->GetWeapon(hWeapon); } } if( m_pWeapon ) { m_pAIWeaponRecord = AIWeaponUtils::GetAIWeaponRecord( m_pWeapon->GetWeaponRecord(), pAI->GetAIBlackBoard()->GetBBAIWeaponOverrideSet() ); } }
void CheckAI(void) { Boolean isai; isai = IsAI( GetCurrPlayer() ); SetFlag( flag_PendingAI, isai ); if( isai ) SetStatus( DS_Thinking ); }
void ShowControl(Word objID, Boolean enable) { if ( !enable || IsAI( stor.currplayer ) ) { CtlHideControl( GetObjectPtr(objID) ); } else { CtlShowControl( GetObjectPtr(objID) ); } }
bool IsDeadAI( HOBJECT hObject ) { if( !hObject ) return true; if( !IsAI( hObject ) ) return false; CCharacter *pCharacter = (CCharacter*)g_pLTServer->HandleToObject( hObject ); return ( pCharacter->GetDestructible()->IsDead() ); }
void ns_HPlayerItem::SetTribe( sint32 tribe ) { m_tribeButton->SetText( g_nsTribes->GetStrings()->GetString( tribe ) ); AllinoneWindow *w = g_allinoneWindow; if ( !IsAI() && w->IsMine( GetPlayer() ) ) spnewgametribescreen_setTribeIndex( tribe - 1, strlen( w->m_lname ) ? w->m_lname : NULL ); }
void DrawRollButton() { if( stor.currplayer < 0 ) { ShowControl( btn_Roll, 1 ); CtlSetLabel( GetObjectPtr(btn_Roll), StartString ); } else { if( IsAI( stor.currplayer ) ) { ShowControl( btn_Roll, 0 ); } else { ShowControl( btn_Roll, 1 ); CtlSetLabel( GetObjectPtr(btn_Roll), RollString ); } } }
void CAIWeaponAbstract::Save(ILTMessage_Write *pMsg) { HOBJECT hOwner = m_pWeapon->GetObject(); ASSERT(IsAI(hOwner)); SAVE_HOBJECT(hOwner); SAVE_HRECORD( m_pWeapon->GetWeaponRecord() ); SAVE_STDSTRING(m_szFireSocketName); SAVE_INT(m_eFiringState); SAVE_DWORD(m_iAnimRandomSeed); SAVE_TIME(m_fRandomSeedSelectionTime); SAVE_FLOAT(m_flWeaponContextInaccuracyScalar); SAVE_DWORD(m_hWeaponSocket); SAVE_bool(m_bCanDropWeapon); }
DieType DialogChooseThree( Char* fText, DieType c1, DieType c2, DieType c3 ) { FormPtr prevForm, frm; UInt16 hitButton; if( IsAI( GetCurrPlayer() ) ) { return AIChooseThree( c1, c2, c3 ); } // Save previous form prevForm = FrmGetActiveForm(); // Init new form frm = FrmInitForm( frmChooseThree ); // Set it FrmSetActiveForm(frm); FrmDrawForm(frm); // Fill it... CtlSetLabel( GetObjectPtr(btnChooseThree1), val2name[c1] ); CtlSetLabel( GetObjectPtr(btnChooseThree2), val2name[c2] ); CtlSetLabel( GetObjectPtr(btnChooseThree3), val2name[c3] ); SetFieldTextFromStr( fldChooseThree, fText ); // Set the handler // FrmSetEventHandler(frm, DialogNewGameHandleEvent); hitButton = FrmDoDialog(frm); // Delete the form, we're not using it FrmDeleteForm(frm); // Restore previous form. if (prevForm) { FrmSetActiveForm(prevForm); } if( hitButton == btnChooseThree1 ) return c1; if( hitButton == btnChooseThree2 ) return c2; if( hitButton == btnChooseThree3 ) return c3; return c1; }
bool CAIActionAttack::ValidateContextPreconditions( CAI* pAI, CAIWorldState& wsWorldStateGoal, bool bIsPlanning ) { // No target. if( !pAI->HasTarget( kTarget_Character | kTarget_CombatOpportunity | kTarget_Object ) ) { return false; } // Target is not visible. if( m_bValidateVisibility ) { if( ( !pAI->GetAIBlackBoard()->GetBBTargetVisibleFromWeapon() ) && ( !IsAI( pAI->GetTarget()->GetVisionBlocker() ) ) ) { return false; } } // AI does not have a weapon of the correct type if (!AIWeaponUtils::HasWeaponType(pAI, GetWeaponType(), bIsPlanning)) { return false; } // Target is not in range. if (!AIWeaponUtils::IsInRange(pAI, GetWeaponType(), bIsPlanning)) { return false; } // AI does not have any ammo required by this weapon type. if ( !AIWeaponUtils::HasAmmo(pAI, GetWeaponType(), bIsPlanning ) ) { return false; } return true; }
bool CAIActionAttack::ValidateAction( CAI* pAI ) { if( !super::ValidateAction( pAI ) ) { return false; } // Target is not visible. // And target is not obscured by an AI. if( m_bValidateVisibility) { if ( !pAI->GetAIBlackBoard()->GetBBTargetVisibleFromWeapon() && ( !IsAI( pAI->GetTarget()->GetVisionBlocker() ) ) ) { return false; } } // Target is not in range. if ( m_bInterruptActionIfEnemyIsOutOfRange ) { if( pAI->GetAIBlackBoard()->GetBBWeaponStatus(GetWeaponType()) != kRangeStatus_Ok ) { return false; } } // Weapon is unloaded. SAIWORLDSTATE_PROP* pProp = pAI->GetAIWorldState()->GetWSProp( kWSK_WeaponLoaded, pAI->m_hObject ); if( pProp && !pProp->bWSValue ) { return false; } return true; }
void Door::HandelLinkTriggerMsg( LTBOOL bTriggerLink ) { // Let our base hadle it first ActiveWorldModel::HandleTriggerMsg( ); // If we are locked then dont do anything else if( m_dwPropFlags & AWM_PROP_LOCKED ) { if( m_nCurState == AWM_STATE_OFF || m_nCurState == AWM_STATE_ON ) { // Tell any doorknobs attached to us to play the "locked" animation... PlayDoorKnobAni( "Locked" ); } return; } if( bTriggerLink ) { // Let our link know that we are opening... // AIs ignore links and open both doors. if( m_nCurState == AWM_STATE_POWERON ) { if( m_hDoorLink && !IsAI( m_hActivateObj ) ) { Door *pDoorLink = (Door*)g_pLTServer->HandleToObject( m_hDoorLink ); if( pDoorLink ) { pDoorLink->TriggerLink( m_hActivateObj ); } } } } }
void CAIGoalAbstractStimulated::ActivateGoal() { super::ActivateGoal(); // Only set a new response index if the AI is witnessing a new stimulus, // rather than seeing an ally who is disturbed. if( ( m_eSenseType != kSense_SeeAllyDisturbance ) && ( m_eSenseType != kSense_HearAllyDisturbance ) ) { m_pAI->SetLastStimulusTime( m_fStimulusTime ); } // Copy an ally's stimulus time. else if( m_hStimulusSource && IsAI( m_hStimulusSource ) ) { CAI* pAlly = (CAI*)( g_pLTServer->HandleToObject( m_hStimulusSource ) ); if( pAlly ) { m_pAI->SetLastStimulusTime( pAlly->GetLastStimulusTime() ); } } }
HOBJECT CAITargetSelectDisturbanceBeyondGuard::SelectDisturbanceSource( CAI* pAI, CAIWMFact* pFact ) { // Sanity check. if( !( pAI && pFact ) ) { return NULL; } // Disturbance is not from an AI. if( !IsAI( pFact->GetTargetObject() ) ) { return pFact->GetTargetObject(); } // AI is not an ally. CAI* pOther = (CAI*)g_pLTServer->HandleToObject( pFact->GetTargetObject() ); EnumCharacterStance eStance = g_pCharacterDB->GetStance( pAI->GetAlignment(), pOther->GetAlignment() ); if( eStance != kCharStance_Like ) { return pFact->GetTargetObject(); } // Ally is not targeting a character. if( pOther->GetAIBlackBoard()->GetBBTargetType() != kTarget_Character ) { return pFact->GetTargetObject(); } // Return the Ally's target object. return pOther->GetAIBlackBoard()->GetBBTargetObject(); }
bool Alarm::OnTrigger(HOBJECT hSender, const CParsedMsg &cMsg) { static CParsedMsg::CToken s_cTok_Activate(s_szActivate); static CParsedMsg::CToken s_cTok_Lock(s_szLock); static CParsedMsg::CToken s_cTok_Unlock(s_szUnlock); if ( cMsg.GetArg(0) == s_cTok_Activate ) { // If the alarm is activated from a command, the sender is // NULL (dammit!). So treat it as player-activated. // If the alarm is activated by something other than AI // (e.g. a command object) consider it player activated. if( !IsAI( hSender ) ) { CPlayerObj *pPlayer = g_pCharacterMgr->FindPlayer(); hSender = pPlayer->m_hObject; } HOBJECT hStimulus = hSender; if( IsPlayer(hSender) ) { // Run the alarm's player-activate command. if( m_hstrPlayerActivateCommand ) { const char *szCmd = g_pLTServer->GetStringData( m_hstrPlayerActivateCommand ); if( g_pCmdMgr->IsValidCmd( szCmd ) ) { g_pCmdMgr->Process( szCmd, m_hObject, m_hObject ); } } } else { // The stimulus is the target of the AI who activated the alarm. CAI* pAI = (CAI*)g_pLTServer->HandleToObject(hSender); hStimulus = pAI->GetTarget()->GetObject(); } // Ensure that lists of Alert and Respond regions are set up. if( ( m_fRegionsGroupRadius == 0.f ) && ( ( m_lstAlertRegions.size() > 0 ) || ( m_lstRespondRegions.size() > 0 ) || ( m_lstSearchRegions.size() > 0 ) ) ) { CalculateRegionsGroupRadius(); } // Place an alarm stimulus. // The stimulus position and radius are set to values that encompass // all of the regions affected by the alarm. g_pAIStimulusMgr->RegisterStimulus(kStim_EnemyAlarmSound, hStimulus, m_hObject, m_vRegionsGroupCenter, m_fRegionsGroupRadius, m_fAlarmSoundTime); AITRACE( AIShowAlarms, ( m_hObject, "Triggering alarm" ) ); } else if ( cMsg.GetArg(0) == s_cTok_Lock ) { m_bLocked = LTTRUE; } else if ( cMsg.GetArg(0) == s_cTok_Unlock ) { m_bLocked = LTFALSE; } else return Prop::OnTrigger(hSender, cMsg); return true; }
void CAISenseRecorderAbstract::HandleSenses(uint32 nCycle) { AISENSE_RECORD_MAP::iterator it; for(it = m_mapSenseRecords.begin(); it != m_mapSenseRecords.end(); ++it) { AISenseRecord* pSenseRecord = it->second; AIBM_Stimulus* pAIBM_Stimulus = pSenseRecord->pAIBM_Last_Stimulus; // If pAIBM_Stimulus is NULL, this sense has never been stimulated. if(pAIBM_Stimulus == LTNULL) { continue; } // Check for senses that were not updated this cycle. // Ignore senses that were not updated this cycle because // of a delayed stimulus. if((pSenseRecord->nCycle != nCycle) && (pSenseRecord->fReactionDelayTimer == 0.f)) { // Decrease the simulation, if there is any. if(pSenseRecord->fCurStimulation > 0.f) { LTBOOL bFalseStimulation = DecreaseStimulation(pSenseRecord, 1.0f); // If not a false stimulation, do not let the state handle the sense. if(!bFalseStimulation) { continue; } // If we have hit the false stimulation limit, treat it as a real stimulation. if( pSenseRecord->cFalseStimulation >= pAIBM_Stimulus->nFalseStimulationLimit ) { pSenseRecord->cFalseStimulation = 0; pSenseRecord->fCurStimulation = pAIBM_Stimulus->rngStimulationThreshhold.GetMax(); pSenseRecord->fMaxStimulation = pAIBM_Stimulus->rngStimulationThreshhold.GetMax(); AITRACE(AIShowSenses, (m_pSensing->GetSensingObject(), "Hit FalseStimulution Limit %d of %s\n", pAIBM_Stimulus->nFalseStimulationLimit, SenseToString(pSenseRecord->eSenseType)) ); } // Treat other false stimulations as other senses, // if an optional FalseStimulusSense was specified. else if( pAIBM_Stimulus->eFalseStimulusSense != kSense_InvalidType ) { AISenseRecord* pFalseStimulationSense = GetSense( pAIBM_Stimulus->eFalseStimulusSense ); if( pFalseStimulationSense ) { pFalseStimulationSense->pAIBM_Last_Stimulus = pAIBM_Stimulus; pFalseStimulationSense->hLastStimulusSource = pSenseRecord->hLastStimulusSource; pFalseStimulationSense->vLastStimulusPos = pSenseRecord->vLastStimulusPos; pFalseStimulationSense->eLastStimulusID = pSenseRecord->eLastStimulusID; pFalseStimulationSense->fCurStimulation = pAIBM_Stimulus->rngStimulationThreshhold.GetMax(); pFalseStimulationSense->fMaxStimulation = pAIBM_Stimulus->rngStimulationThreshhold.GetMax(); pFalseStimulationSense->fLastStimulationTime = pSenseRecord->fLastStimulationTime; pFalseStimulationSense->nLastStimulusAlarmLevel = 1; pFalseStimulationSense->nCycle = nCycle; } } } } // Invalidate hiding spots if AI can already see player. if( ( pSenseRecord->eSenseType == kSense_SeeEnemy ) && IsPlayer( pSenseRecord->hLastStimulusSource ) && IsAI( m_pSensing->GetSensingObject() ) && ( pSenseRecord->fCurStimulation >= 0.5f ) ) { CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject( pSenseRecord->hLastStimulusSource ); CAI* pAI = (CAI*)g_pLTServer->HandleToObject( m_pSensing->GetSensingObject() ); if( pPlayer && pAI ) { pPlayer->SetVisibleToEnemyAI( pAI, true ); } } // Check if we're fully stimulated. if(pSenseRecord->fCurStimulation >= pAIBM_Stimulus->rngStimulationThreshhold.GetMax()) { // Wait for, or increment, ReactionDelay. if(pSenseRecord->fReactionDelayTimer >= pSenseRecord->fReactionDelayTime) { m_pSensing->HandleSenseTrigger( pSenseRecord ); pSenseRecord->fReactionDelayTimer = 0.f; pSenseRecord->fReactionDelayTime = 0.f; } else pSenseRecord->fReactionDelayTimer += m_pSensing->GetSenseUpdateRate(); } } }
void CAITargetSelectDisturbance::TargetDisturbance( CAI* pAI, CAIWMFact* pFact ) { // Sanity check. if( !( pAI && pFact ) ) { return; } // Record the existence of a disturbance in the AI's world state. pAI->GetAIWorldState()->SetWSProp( kWSK_DisturbanceExists, pAI->m_hObject, kWST_bool, true ); // Play a sound corresponding to the type of stimulus. EnumAIStimulusID eStimulusID; EnumAIStimulusType eStimulusType; pFact->GetStimulus( &eStimulusType, &eStimulusID ); switch( eStimulusType ) { case kStim_WeaponFireSound: case kStim_WeaponImpactSound: case kStim_WeaponReloadSound: case kStim_DisturbanceSound: case kStim_FootstepSound: case kStim_DeathSound: case kStim_PainSound: { HOBJECT hAlly = g_pAICoordinator->FindAlly( pAI->m_hObject, NULL ); if( hAlly ) { // "Check it out!" // "Roger!" g_pAISoundMgr->RequestAISound( pAI->m_hObject, kAIS_OrderInvestigate, kAISndCat_DisturbanceHeard, NULL, 1.f ); g_pAISoundMgr->RequestAISoundSequence( hAlly, kAIS_Affirmative, pAI->m_hObject, kAIS_OrderInvestigate, kAIS_OrderInvestigate, kAISndCat_Event, NULL, 0.3f ); } else { // "What was that?" g_pAISoundMgr->RequestAISound( pAI->m_hObject, kAIS_DisturbanceHeardAlarming, kAISndCat_DisturbanceHeard, NULL, 1.f ); } } break; // "Flashlight!" case kStim_FlashlightBeamVisible: { g_pAISoundMgr->RequestAISound( pAI->m_hObject, kAIS_DisturbanceSeenFlashlight, kAISndCat_Event, NULL, 0.5f ); HOBJECT hAlly = g_pAICoordinator->FindAlly( pAI->m_hObject, NULL ); if( hAlly ) { // "Check it out!" // "Roger!" g_pAISoundMgr->RequestAISoundSequence( hAlly, kAIS_OrderInvestigate, pAI->m_hObject, kAIS_DisturbanceSeenFlashlight, kAIS_DisturbanceSeenFlashlight, kAISndCat_DisturbanceHeard, NULL, 0.3f ); g_pAISoundMgr->RequestAISoundSequence( pAI->m_hObject, kAIS_Affirmative, hAlly, kAIS_OrderInvestigate, kAIS_DisturbanceSeenFlashlight, kAISndCat_Event, NULL, 0.3f ); } } break; } // Record new target on the BlackBoard. pAI->GetAIBlackBoard()->SetBBTargetType( kTarget_Disturbance ); pAI->GetAIBlackBoard()->SetBBTargetStimulusType( eStimulusType ); pAI->GetAIBlackBoard()->SetBBTargetStimulusID( eStimulusID ); pAI->GetAIBlackBoard()->SetBBTargetChangeTime( g_pLTServer->GetTime() ); pAI->GetAIBlackBoard()->SetBBTargetObject( pFact->GetTargetObject() ); // Record initial disturbance position. // If the stimulus is dynamic, AITarget will track its movement. LTVector vTargetPos = pFact->GetPos(); pAI->GetAIBlackBoard()->SetBBTargetPosition( vTargetPos ); // If the disturbance is coming from an ally's weapon fire sound, // then treat the disturbance position as the position of whatever // the ally is firing at. if( IsAI( pFact->GetTargetObject() ) ) { CAI* pOtherAI = (CAI*)g_pLTServer->HandleToObject( pFact->GetTargetObject() ); if( pOtherAI && pOtherAI->HasTarget( kTarget_Character ) && ( eStimulusType == kStim_WeaponFireSound ) && ( kCharStance_Like == g_pCharacterDB->GetStance( pAI->GetAlignment(), pOtherAI->GetAlignment() ) ) ) { LTVector vTargetPos = pOtherAI->GetAIBlackBoard()->GetBBTargetPosition(); pAI->GetAIBlackBoard()->SetBBTargetPosition( vTargetPos ); pFact->SetPos( vTargetPos, 1.f ); } } }
LTBOOL DoVectorFilterFn(HOBJECT hObj, void *pUserData) { // We're not attacking our self... if (SpecificObjectFilterFn(hObj, pUserData)) { // CharacterHitBox objects are used for vector impacts, don't // impact on the character/body prop object itself.... if (IsCharacter(hObj) || IsBody(hObj) || IsKindOf(hObj, "Intelligence")) { return LTFALSE; } // Check special character hit box cases... if (IsCharacterHitBox(hObj)) { CCharacterHitBox *pCharHitBox = (CCharacterHitBox*) g_pLTServer->HandleToObject(hObj); if (pCharHitBox) { // Make sure we don't hit ourself... HOBJECT hUs = (HOBJECT)pUserData; HOBJECT hTestObj = pCharHitBox->GetModelObject(); if (!hTestObj) return LTFALSE; if (hTestObj == hUs) { return LTFALSE; } // Do special AI hitting AI case... if (IsAI(hUs) && IsAI(hTestObj)) { CAI *pAI = (CAI*) g_pLTServer->HandleToObject(hUs); if (!pAI) return LTFALSE; // We can't hit guys we like, unless they're NEUTRAL CCharacter* pB = (CCharacter*)g_pLTServer->HandleToObject(hTestObj); if (!pB) return LTFALSE; CharacterClass cc = pB->GetCharacterClass(); if (cc != NEUTRAL) { return LIKE != GetAlignement(pAI->GetCharacterClass(), cc); } } // Check for friendly fire if (g_pGameServerShell->GetGameType() == COOPERATIVE_ASSAULT && g_vtNetFriendlyFire.GetFloat() < 1.0f) { // We can't hit guys on our team unless friendly fire is turned on if (IsPlayer(hUs) && IsPlayer(hTestObj)) { CPlayerObj* pUs = (CPlayerObj*) g_pLTServer->HandleToObject(hUs); if (!pUs) return LTFALSE; CPlayerObj* pThem = (CPlayerObj*) g_pLTServer->HandleToObject(hTestObj); if (!pThem) return LTFALSE; if (pUs->GetTeamID() == pThem->GetTeamID()) return LTFALSE; } } } } return LTTRUE; } return LTFALSE; }
bool ObjectRemover::AllObjectsCreated() { HOBJECT ahObjects[kMaxGroups][kMaxObjectsPerGroup][128]; memset(ahObjects, 0, sizeof(HOBJECT)*kMaxGroups*kMaxObjectsPerGroup*128); int cGroupsWithObjects = 0; {for ( int iGroup = 0 ; iGroup < kMaxGroups ; iGroup++ ) { bool bGroupHasObjects = false; {for ( int iObject = 0 ; iObject < kMaxObjectsPerGroup ; iObject++ ) { if ( !m_astrObjects[iGroup][iObject].empty() ) { char szString[1024]; strcpy(szString, m_astrObjects[iGroup][iObject].c_str()); uint32 cTokens = 0; const char* szToken = strtok(szString, ";"); while ( szToken ) { HOBJECT hObject; if ( LT_OK == FindNamedObject(szToken, hObject) ) { ahObjects[cGroupsWithObjects][iObject][cTokens++] = hObject; bGroupHasObjects = true; } szToken = strtok(NULL, ";"); } } }} if ( bGroupHasObjects ) { cGroupsWithObjects++; } }} // Remove the objects bool abRemoved[kMaxGroups]; memset(abRemoved, false, sizeof(bool)*kMaxGroups); int iSafety = 50000; int cRemove = cGroupsWithObjects-m_cGroupsToKeep; while ( (cRemove > 0) && (--iSafety > 0) ) { int iRemove = GetRandom(0, cGroupsWithObjects-1); if ( !abRemoved[iRemove] ) { for ( int iObject = 0 ; iObject < kMaxObjectsPerGroup ; iObject++ ) { for ( int iToken = 0 ; iToken < 128 ; iToken++ ) { if ( ahObjects[iRemove][iObject][iToken] ) { if ( IsAI(ahObjects[iRemove][iObject][iToken]) ) { ILTBaseClass *pAI = g_pLTServer->HandleToObject( ahObjects[iRemove][iObject][iToken] ); g_pCmdMgr->QueueMessage( this, pAI, "REMOVE" ); } else { g_pLTServer->RemoveObject(ahObjects[iRemove][iObject][iToken]); } } } } abRemoved[iRemove] = true; cRemove--; } } // Remove ourselves... g_pLTServer->RemoveObject(m_hObject); return true; }
void CAIGoalDrawWeapon::ActivateGoal() { super::ActivateGoal(); // Bail if no holstered weapon, or already have a weapon armed. if( ( !m_pAI->HasHolsterString() ) || ( m_pAI->GetPrimaryWeapon() ) ) { m_fCurImportance = 0.f; return; } // ASSERT(m_hStimulusSource != LTNULL); // Ignore senses other than see enemy. m_pAI->SetCurSenseFlags( kSense_SeeEnemy | kSense_SeeDangerousProjectile | kSense_SeeCatchableProjectile ); m_pGoalMgr->LockGoal( this ); // Set Draw state. m_pAI->SetState( kState_HumanDraw ); if( m_pAI->GetAlarmLevel() >= m_pAI->GetBrain()->GetMajorAlarmThreshold() ) { m_pAI->SetAwareness( kAware_Alert ); } // If stimulated by an AI, target whatever he is targeting. if( IsAI( m_hStimulusSource ) ) { CAI* pAI = (CAI*)g_pLTServer->HandleToObject( m_hStimulusSource ); if( pAI ) { if( pAI->HasTarget() ) { m_pAI->Target( pAI->GetTarget()->GetObject() ); } } } else if( IsCharacter( m_hStimulusSource ) ) { // Only set a target to turn towards for specified senses. switch( m_eSenseType ) { case kSense_SeeEnemy: case kSense_SeeEnemyLean: case kSense_HearEnemyWeaponFire: case kSense_HearEnemyFootstep: { // Only target hated characters. CCharacter *pChar = (CCharacter*)g_pLTServer->HandleToObject( m_hStimulusSource ); if( pChar ) { CharacterAlignment eAlignment = GetAlignment( pChar->GetRelationSet(), m_pAI->GetRelationData() ); if( eAlignment == HATE ) { m_pAI->Target( m_hStimulusSource ); CAIHumanStateDraw* pStateDraw = (CAIHumanStateDraw*)m_pAI->GetState(); pStateDraw->SetFaceTarget( LTTRUE ); } } } break; } } }
bool CAISensorStatusCheck::StimulateSensor( CAIStimulusRecord* pStimulusRecord ) { // Intentionally do NOT call super::StimulateSensor. // This sensor only exists to play dialog based on lack of stimulation. // Sanity check. if( !pStimulusRecord ) { return false; } // Template specifies accepted stimuli. if( !( m_pSensorRecord->dwStimulusTypes & pStimulusRecord->m_eStimulusType ) ) { return false; } // Ignore stimuli targeting myself. if( pStimulusRecord->m_hStimulusTarget == m_pAI->m_hObject ) { return false; } // Ignore stimuli targeting something other than an AI. if( !IsAI( pStimulusRecord->m_hStimulusTarget ) ) { return false; } // Bail if we are waiting on something detecting previously. if( m_fStatusCheckTime > g_pLTServer->GetTime() ) { return false; } // Stimulus is too far away to be sensed. float fDistanceSqr = pStimulusRecord->m_vStimulusPos.DistSqr( m_pAI->GetPosition() ); if( fDistanceSqr > GetSenseDistSqr( pStimulusRecord->m_fDistance ) ) { return false; } // Bail if someone has performed a status check recently. // Add a one second leniency on the time, to ensure we catch // cases where someone would have seen an impact just as the // timeout expired. CAIWMFact factTimeQuery; factTimeQuery.SetFactType( kFact_Knowledge ); factTimeQuery.SetKnowledgeType( kKnowledge_NextStatusCheckTime ); CAIWMFact* pFactTime = g_pAIWorkingMemoryCentral->FindWMFact(factTimeQuery); if( pFactTime && ( pFactTime->GetTime() - 1.f > g_pLTServer->GetTime() ) ) { return false; } // Bail if someone has already seen this impact. CAIWMFact factQuery; factQuery.SetFactType( kFact_Knowledge ); factQuery.SetKnowledgeType( kKnowledge_WitnessedStimulus ); factQuery.SetStimulus( kStim_WeaponImpactVisible, pStimulusRecord->m_eStimulusID ); CAIWMFact* pFact = g_pAIWorkingMemoryCentral->FindWMFact(factQuery); if( pFact ) { return false; } // Determine if stimulus can truly be sensed, using optional specific checks. float fRateModifier = 1.f; bool bStimulated = DoComplexCheck( pStimulusRecord, &fRateModifier ); if( bStimulated ) { // Record that someone has seen this impact. pFact = g_pAIWorkingMemoryCentral->CreateWMFact( kFact_Knowledge ); pFact->SetKnowledgeType( kKnowledge_WitnessedStimulus, 1.f ); pFact->SetStimulus( kStim_WeaponImpactVisible, pStimulusRecord->m_eStimulusID, 1.f ); return true; } // AI cannot see the stimulus. // Check back in a second to see if anyone else has seen it. // The AI should only do a status check if no one can see the threat. m_fStatusCheckTime = g_pLTServer->GetTime() + 1.f; m_eStimulusIDToCheck = pStimulusRecord->m_eStimulusID; m_hAlly = pStimulusRecord->m_hStimulusTarget; // Sensor was not actually stimulated. return false; }
void CSpear::HandleImpact(HOBJECT hObj) { if (!g_vtSpearStickPercentage.IsInitted()) { g_vtSpearStickPercentage.Init(g_pLTServer, "SpearStickPercent", LTNULL, 0.9f); } if (!m_pAmmoData || !m_pAmmoData->pProjectileFX) { CProjectile::HandleImpact(hObj); return; } CollisionInfo info; g_pLTServer->GetLastCollision(&info); LTVector vPos, vVel, vCurVel, vP0, vP1; g_pLTServer->GetObjectPos(m_hObject, &vPos); LTRotation rRot; g_pLTServer->GetObjectRotation(m_hObject, &rRot); // Should we break the spear? enum SpearAction { eSpearActionBreak, eSpearActionStickWorld, eSpearActionStickAI, eSpearActionStickPlayer, eSpearActionStickBody }; SpearAction eSpearAction = eSpearActionBreak; // Randomly break even if we could sometimes stick... if (GetRandom(0.0, 1.0f) > g_vtSpearStickPercentage.GetFloat()) { eSpearAction = eSpearActionBreak; } else if (IsMainWorld(hObj)) { // Calculate where we really hit the world... g_pLTServer->GetVelocity(m_hObject, &vVel); vP1 = vPos; vCurVel = vVel * g_pLTServer->GetFrameTime(); vP0 = vP1 - vCurVel; vP1 += vCurVel; LTFLOAT fDot1 = VEC_DOT(info.m_Plane.m_Normal, vP0) - info.m_Plane.m_Dist; LTFLOAT fDot2 = VEC_DOT(info.m_Plane.m_Normal, vP1) - info.m_Plane.m_Dist; if (fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f) { vPos = vP1; } else { LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1); VEC_LERP(vPos, vP0, vP1, fPercent); } // Set our new "real" pos... g_pLTServer->SetObjectPos(m_hObject, &vPos); eSpearAction = eSpearActionStickWorld; } else if (IsMoveable(hObj)) { if (IsAI(hObj)) { // Attach to a AI eSpearAction = eSpearActionStickAI; } else if (IsPlayer(hObj)) { // Attach to a Player eSpearAction = eSpearActionStickPlayer; } else if (IsBody(hObj)) { // Attach to a body eSpearAction = eSpearActionStickBody; } else { // Could probably come up with a way to attach to moveable // non-character objects (like doors), but it is much easier // to just break it ;)... eSpearAction = eSpearActionBreak; } } // If the surface is too hard, the spear will just break when // it hits it... SurfaceType eSurf = GetSurfaceType(info); SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eSurf); if ((eSpearActionBreak == eSpearAction) || ((eSpearActionStickWorld == eSpearAction) && pSurf && pSurf->fHardness > 0.5)) { // Create spear debris... DEBRIS* pDebris = g_pDebrisMgr->GetDebris(m_pAmmoData->szName); if (pDebris) { vVel.Norm(); LTVector vNegVel = -vVel; CreatePropDebris(vPos, vNegVel, pDebris->nId); } CProjectile::HandleImpact(hObj); return; } // Create the Spear powerup... char szSpawn[512]; sprintf(szSpawn, "AmmoBox AmmoType1 %s;AmmoCount1 1;Filename %s;Skin %s", m_pAmmoData->szName, m_pAmmoData->pProjectileFX->szModel, m_pAmmoData->pProjectileFX->szSkin); LTVector vScale = m_pAmmoData->pProjectileFX->vModelScale; // Make sure the spear sticks out a little ways... vVel.Norm(); vPos -= (vVel * vScale.z/2.0f); if (eSpearActionStickWorld == eSpearAction) { g_pLTServer->AlignRotation(&rRot, &vVel, LTNULL); } BaseClass* pClass = SpawnObject(szSpawn, LTVector(-10000,-10000,-10000), rRot); if (pClass) { g_pLTServer->ScaleObject(pClass->m_hObject, &vScale); LTVector vDims; g_pLTServer->GetObjectDims(pClass->m_hObject, &vDims); vDims.x *= vScale.x; vDims.y *= vScale.y; vDims.z *= vScale.z; g_pLTServer->SetObjectDims(pClass->m_hObject, &vDims); // We don't want other projectiles to impact on us... //uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(pClass->m_hObject); //dwUsrFlags |= USRFLG_IGNORE_PROJECTILES; //g_pLTServer->SetObjectUserFlags(pClass->m_hObject, dwUsrFlags); if ( eSpearActionStickAI == eSpearAction || eSpearActionStickPlayer == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) & ~USRFLG_GLOW); g_pLTServer->SetObjectFlags(pClass->m_hObject, g_pLTServer->GetObjectFlags(pClass->m_hObject) & ~FLAG_TOUCH_NOTIFY); if ( eSpearActionStickPlayer == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) | USRFLG_ATTACH_HIDE1SHOW3); } // Attach it to the character CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(hObj); pCharacter->AddSpear(pClass->m_hObject, pCharacter->GetModelNodeLastHit(), rRot); } else if ( eSpearActionStickBody == eSpearAction ) { g_pLTServer->SetObjectUserFlags(pClass->m_hObject, g_pLTServer->GetObjectUserFlags(pClass->m_hObject) & ~USRFLG_GLOW); g_pLTServer->SetObjectFlags(pClass->m_hObject, g_pLTServer->GetObjectFlags(pClass->m_hObject) & ~FLAG_TOUCH_NOTIFY); // Attach it to the body Body* pBody = (Body*)g_pLTServer->HandleToObject(hObj); pBody->AddSpear(pClass->m_hObject, rRot); } else // ( eSpearActionStickWorld == eSpearAction ) { // Move it to the right position in the world g_pLTServer->SetObjectPos(pClass->m_hObject, &vPos); } } CProjectile::HandleImpact(hObj); }