bool CMissionManager::DoCopyFile(const fs::path& source, const fs::path& dest, bool overwrite) { if (overwrite) { try { // According to docs, remove() doesn't throw if file doesn't exist fs::remove(dest); DM_LOG(LC_MAINMENU, LT_INFO)LOGSTRING("Destination file %s already exists, has been removed before copying.\r", dest.string().c_str()); } catch (fs::filesystem_error& e) { // Don't care about removal error DM_LOG(LC_MAINMENU, LT_DEBUG)LOGSTRING("Caught exception while removing destination file %s: %s\r", dest.string().c_str(), e.what()); } } // Copy the source file to the destination try { fs::copy_file(source, dest); DM_LOG(LC_MAINMENU, LT_INFO)LOGSTRING("File successfully copied to %s.\r", dest.string().c_str()); return true; } catch (fs::filesystem_error& e) { DM_LOG(LC_MAINMENU, LT_ERROR)LOGSTRING("Exception while coyping file from %s to %s: %s\r", source.string().c_str(), dest.string().c_str(), e.what()); return false; } }
void DifficultyManager::LoadDefaultDifficultySettings() { DM_LOG( LC_DIFFICULTY, LT_INFO )LOGSTRING( "Trying to load default difficulty settings from entityDefs.\r" ); // Construct the entityDef name (e.g. atdm:difficulty_settings_default) idStr defName( DEFAULT_DIFFICULTY_ENTITYDEF ); const idDict *difficultyDict = gameLocal.FindEntityDefDict( defName, true ); // grayman #3391 - don't create a default 'difficultyDict' // We want 'false' here, but FindEntityDefDict() // will print its own warning, so let's not // clutter the console with a redundant message if( difficultyDict != NULL ) { DM_LOG( LC_DIFFICULTY, LT_DEBUG )LOGSTRING( "Found difficulty settings: %s.\r", defName.c_str() ); // greebo: Try to lookup the entityDef for each difficulty level and load the settings for( int i = 0; i < DIFFICULTY_COUNT; i++ ) { // Let the setting structure know which level it is referring to _globalSettings[i].SetLevel( i ); // And load the settings _globalSettings[i].LoadFromEntityDef( *difficultyDict ); // Load the CVAR settings too _cvarSettings[i].SetLevel( i ); _cvarSettings[i].LoadFromEntityDef( *difficultyDict ); } } else { for( int i = 0; i < DIFFICULTY_COUNT; i++ ) { _globalSettings[i].Clear(); _cvarSettings[i].Clear(); } gameLocal.Warning( "DifficultyManager: Could not find default difficulty entityDef!" ); } }
void DifficultyManager::Init( idMapFile *mapFile ) { DM_LOG( LC_DIFFICULTY, LT_INFO )LOGSTRING( "Searching for difficulty setting on worldspawn.\r" ); if( mapFile->GetNumEntities() <= 0 ) { return; // no entities! } // Fetch the worldspawn idMapEntity *mapEnt = mapFile->GetEntity( 0 ); idDict spawnArgs = mapEnt->epairs; int mapDifficulty; if( spawnArgs.GetInt( "difficulty", "0", mapDifficulty ) ) { // We have a difficulty spawnarg set on the map's worldspawn, take it as override value DM_LOG( LC_DIFFICULTY, LT_DEBUG )LOGSTRING( "Found overriding difficulty setting on worldspawn entity: %d.\r", mapDifficulty ); _difficulty = mapDifficulty; } // Check for the CVAR, which might override any setting if( cv_tdm_difficulty.GetInteger() >= 0 ) { _difficulty = cv_tdm_difficulty.GetInteger(); DM_LOG( LC_DIFFICULTY, LT_DEBUG )LOGSTRING( "Found overriding CVAR 'tdm_difficulty': %d.\r", _difficulty ); } // Clear the CVAR settings before parsing for( int i = 0; i < DIFFICULTY_COUNT; i++ ) { _cvarSettings[i].Clear(); } // Load the default difficulty settings from the entityDefs LoadDefaultDifficultySettings(); LoadMapDifficultySettings( mapFile ); }
void DifficultySettings::ApplySettings(idDict& target) { std::string eclass = target.GetString("classname"); if (eclass.empty()) { return; // no classname, no rules } // greebo: First, get the list of entity-specific difficulty settings from the dictionary // Everything processed here will be ignored in the second run (where the default settings are applied) idList<Setting> entSettings = Setting::ParseSettingsFromDict(target, _level); DM_LOG(LC_DIFFICULTY, LT_DEBUG)LOGSTRING("Found %d difficulty settings on the entity %s.\r", entSettings.Num(), target.GetString("name")); // Apply the settings one by one for (int i = 0; i < entSettings.Num(); i++) { DM_LOG(LC_DIFFICULTY, LT_DEBUG)LOGSTRING("Applying entity-specific setting: %s => %s.\r", entSettings[i].spawnArg.c_str(), entSettings[i].argument.c_str()); entSettings[i].Apply(target); } // Second step: apply global settings // Get the inheritancechain for the given target dict const InheritanceChain &inheritanceChain = GetInheritanceChain(target); // Go through the inheritance chain front to back and apply the settings for (InheritanceChain::const_iterator c = inheritanceChain.begin(); c != inheritanceChain.end(); ++c) { std::string className = *c; // Process the list of default settings that apply to this entity class, // but ignore all keys that have been addressed by the entity-specific settings. for (SettingsMap::iterator i = _settings.find(className); i != _settings.upper_bound(className) && i != _settings.end(); ++i) { Setting& setting = i->second; bool settingApplicable = true; // Check if the spawnarg has been processed in the entity-specific settings for (int k = 0; k < entSettings.Num(); k++) { if (entSettings[k].spawnArg == setting.spawnArg) { // This target spawnarg has already been processed in the first run, skip it DM_LOG(LC_DIFFICULTY, LT_DEBUG)LOGSTRING("Ignoring global setting: %s => %s.\r", setting.spawnArg.c_str(), setting.argument.c_str()); settingApplicable = false; break; } } if (settingApplicable) { // We have green light, apply the setting DM_LOG(LC_DIFFICULTY, LT_DEBUG)LOGSTRING("Applying global setting: %s => %s.\r", setting.spawnArg.c_str(), setting.argument.c_str()); setting.Apply(target); } } } }
bool MeleeCombatTask::Perform(Subsystem& subsystem) { DM_LOG(LC_AI, LT_INFO)LOGSTRING("Melee Combat Task performing.\r"); idAI* ownerEnt = _owner.GetEntity(); assert(ownerEnt != NULL); idActor* enemy = _enemy.GetEntity(); if ( ( enemy == NULL ) || enemy->IsKnockedOut() || ( enemy->health <= 0 ) ) { DM_LOG(LC_AI, LT_DEBUG)LOGSTRING("No enemy, terminating task!\r"); return true; // terminate me } // Perform the task according to the current action EMeleeActState actState = ownerEnt->m_MeleeStatus.m_ActionState; switch (actState) { case MELEEACTION_READY: PerformReady(ownerEnt); break; case MELEEACTION_ATTACK: PerformAttack(ownerEnt); break; case MELEEACTION_PARRY: PerformParry(ownerEnt); break; default: PerformReady(ownerEnt); }; return false; // not finished yet }
void CStimResponseCollection::InitFromSpawnargs(const idDict& args, idEntity* owner) { if (owner == NULL) { DM_LOG(LC_STIM_RESPONSE, LT_ERROR)LOGSTRING("Owner set to NULL is not allowed!\r"); return; } idStr name; for (int i = 1; /* in-loop break */; ++i) { idStr name = va("sr_class_%u", i); DM_LOG(LC_STIM_RESPONSE, LT_DEBUG)LOGSTRING("Looking for %s\r", name.c_str()); idStr str; if (!args.GetString(name, "X", str)) { break; } char sr_class = str[0]; if (ParseSpawnArg(args, owner, sr_class, i) == false) { break; } } }
bool CStimResponse::CheckChance() { if( m_Chance < 1.0f ) { // Chance timer still active? if( m_NextChanceTime > gameLocal.GetTime() ) { DM_LOG( LC_STIM_RESPONSE, LT_DEBUG )LOGSTRING( "CStimResponse::checkChance: Timeout still active.\r" ); // Next chance time is still in the future, return false return false; } // The stim only fires if the (hopefully uniformly distributed) // random variable is within the interval (0, m_Chance] if( gameLocal.random.RandomFloat() <= m_Chance ) { // Reset the next chance time m_NextChanceTime = -1; return true; } else { DM_LOG( LC_STIM_RESPONSE, LT_DEBUG )LOGSTRING( "CStimResponse::checkChance: Chance test failed.\r" ); // Test failed, should we use a timeout? if( m_ChanceTimer > 0 ) { // Save the earliest time of the next response chance m_NextChanceTime = gameLocal.GetTime() + m_ChanceTimer; } return false; } } else { // 100% chance => return true return true; } }
bool PathWaitTask::Perform(Subsystem& subsystem) { DM_LOG(LC_AI, LT_INFO)LOGSTRING("PathWaitTask performing.\r"); idPathCorner* path = _path.GetEntity(); idAI* owner = _owner.GetEntity(); // This task may not be performed with empty entity pointers assert(path != NULL && owner != NULL); if (gameLocal.time >= _endtime) { // Trigger path targets, now that we're done waiting // grayman #3670 - need to keep the owner->Activate() calls to not break // existing maps, but the intent was path->Activate(). owner->ActivateTargets(owner); path->ActivateTargets(owner); // NextPath(); // Wait is done, fall back to PatrolTask DM_LOG(LC_AI, LT_INFO)LOGSTRING("Wait is done.\r"); return true; // finish this task } return false; }
void ConversationSystem::ProcessConversations() { // Remove the dying conversations first for( int i = 0; i < _dyingConversations.Num(); i++ ) { // Remove the dying index from the active conversations list _activeConversations.Remove( _dyingConversations[i] ); } _dyingConversations.Clear(); // What remains is a list of active conversations for( int i = 0; i < _activeConversations.Num(); i++ ) { ConversationPtr conv = GetConversation( _activeConversations[i] ); assert( conv != NULL ); // Let the conversation do its job if( !conv->Process() ) { // Job returned false, terminate this conversation DM_LOG( LC_CONVERSATION, LT_DEBUG )LOGSTRING( "Terminating conversation %s due to error.\r", conv->GetName().c_str() ); EndConversation( _activeConversations[i] ); continue; } // Check if the conversation is done if( conv->IsDone() ) { // Job returned false, terminate this conversation DM_LOG( LC_CONVERSATION, LT_INFO )LOGSTRING( "Conversation %s finished normally.\r", conv->GetName().c_str() ); EndConversation( _activeConversations[i] ); continue; } } }
void CFrobLock::Event_TriggerUnlockTargets() { bool updateFrobability = spawnArgs.GetBool("update_target_frobability", "0"); for (const idKeyValue* kv = spawnArgs.MatchPrefix("unlock_target"); kv != NULL; kv = spawnArgs.MatchPrefix("unlock_target", kv)) { // Find the entity idEntity* unlockTarget = gameLocal.FindEntity(kv->GetValue()); if (unlockTarget == NULL) { DM_LOG(LC_LOCKPICK, LT_DEBUG)LOGSTRING("Could not find unlock target %s (this: %s)\r", kv->GetValue().c_str(), name.c_str()); continue; } DM_LOG(LC_LOCKPICK, LT_INFO)LOGSTRING("Activating unlock target %s\r", kv->GetValue().c_str()); unlockTarget->Activate(this); if (updateFrobability) { DM_LOG(LC_LOCKPICK, LT_INFO)LOGSTRING("Enabling unlock target frobability: %s\r", unlockTarget->name.c_str()); unlockTarget->SetFrobable(true); } } }
void CMissionManager::UninstallMod() { // To uninstall the current FM, just clear the FM name in currentfm.txt WriteCurrentFmFile(""); #if 0 // Path to the darkmod directory fs::path darkmodPath = GetDarkmodPath(); // Path to file that holds the current FM name fs::path currentFMPath(darkmodPath / cv_tdm_fm_current_file.GetString()); DM_LOG(LC_MAINMENU, LT_DEBUG)LOGSTRING("Trying to clear current FM name in %s\r", currentFMPath.file_string().c_str()); if (DoRemoveFile(currentFMPath)) { DM_LOG(LC_MAINMENU, LT_INFO)LOGSTRING("Current FM file removed: %s.\r", currentFMPath.string().c_str()); } else { // Log removal error DM_LOG(LC_MAINMENU, LT_DEBUG)LOGSTRING("Caught exception while removing current FM file %s.\r", currentFMPath.string().c_str()); } #endif }
bool MoveToCoverTask::Perform(Subsystem& subsystem) { DM_LOG(LC_AI, LT_INFO)LOGSTRING("Move to Cover Task performing.\r"); idAI* owner = _owner.GetEntity(); // This task may not be performed with empty entity pointer assert(owner != NULL); if (owner->AI_DEST_UNREACHABLE) { //TODO DM_LOG(LC_AI, LT_INFO)LOGSTRING("Destination unreachable.\r"); return true; } if (owner->AI_MOVE_DONE) { // Move is done, DM_LOG(LC_AI, LT_INFO)LOGSTRING("Move is done.\r"); owner->TurnToward(owner->lastVisibleEnemyPos); // finish this task return true; } return false; // not finished yet }
void CResponseEffect::runScript(idEntity* owner, idEntity* stimEntity, float magnitude) { if (!_scriptFunctionValid) { if (owner == NULL) { DM_LOG(LC_STIM_RESPONSE, LT_ERROR)LOGSTRING("Cannot restore scriptfunction, owner is NULL: %s\r", _scriptName.c_str()); return; } _scriptFunctionValid = true; if (_localScript) { // Local scriptfunction _scriptFunction = owner->scriptObject.GetFunction(_scriptName.c_str()); } else { // Global Method _scriptFunction = gameLocal.program.FindFunction(_scriptName.c_str()); } } if ( _scriptFunction == NULL ) { return; } DM_LOG(LC_STIM_RESPONSE, LT_DEBUG)LOGSTRING("Running ResponseEffect Script %s, effectPostfix = %s...\r", _scriptFunction->Name(), _effectPostfix.c_str()); idThread *pThread = new idThread(_scriptFunction); int n = pThread->GetThreadNum(); pThread->CallFunctionArgs(_scriptFunction, true, "eesff", owner, stimEntity, _effectPostfix.c_str(), magnitude, n); pThread->DelayedStart(0); }
CMissionManager::InstallResult CMissionManager::InstallMod(const idStr& name) { CModInfoPtr info = GetModInfo(name); // result is always non-NULL const idStr& modName = info->modName; // Ensure that the target folder exists fs::path targetFolder = g_Global.GetModPath(modName.c_str()); if (!fs::create_directory(targetFolder)) { // Directory exists, not a problem, but log this DM_LOG(LC_MAINMENU, LT_DEBUG)LOGSTRING("FM targetFolder already exists: %s\r", targetFolder.string().c_str()); } #if 0 // Path to the darkmod directory fs::path darkmodPath = GetDarkmodPath(); // greebo: We don't copy PK4s around anymore, they remain in the fms/ subfolders // Copy all PK4s from the FM folder (and all subdirectories) idFileList* pk4Files = fileSystem->ListFilesTree(info->pathToFMPackage, ".pk4", false); for (int i = 0; i < pk4Files->GetNumFiles(); ++i) { // Source file (full OS path) fs::path pk4fileOsPath = GetDarkmodPath() / pk4Files->GetFile(i); // Target location fs::path targetFile = targetFolder / pk4fileOsPath.leaf(); DM_LOG(LC_MAINMENU, LT_DEBUG)LOGSTRING("Copying file %s to %s\r", pk4fileOsPath.string().c_str(), targetFile.string().c_str()); // Use boost::filesystem instead of id's (comments state that copying large files can be problematic) //fileeSystem->CopyFile(pk4fileOsPath, targetFile.string().c_str()); // Copy the PK4 file and make sure any target file with the same name is removed beforehand if (!DoCopyFile(pk4fileOsPath, targetFile, true)) { // Failed copying return COPY_FAILURE; } } fileSystem->FreeFileList(pk4Files); #endif // Save the name to currentfm.txt WriteCurrentFmFile(modName); // taaaki: now that fms are loaded directly from <basepath>/darkmod/fms/ // we don't need to copy config files around (i.e. just use the // one in <basepath>/darkmod/ (same with config.spec) return INSTALLED_OK; }
CInventoryItemPtr CInventory::ValidateWeapon(idEntity* ent, const bool gotFromShop) // grayman (#2376) { // Sanity check if (ent == NULL) return CInventoryItemPtr(); idStr weaponName = ent->spawnArgs.GetString("inv_weapon_name"); if (weaponName.IsEmpty()) { // Not a weapon item return CInventoryItemPtr(); } // Entity has a weapon name set, check for match in our inventory // Find the weapon category CInventoryCategoryPtr weaponCategory = GetCategory(TDM_PLAYER_WEAPON_CATEGORY); if (weaponCategory == NULL) { DM_LOG(LC_INVENTORY, LT_ERROR)LOGSTRING("Could not find weapon category in inventory.\r"); return CInventoryItemPtr(); } // Look for the weapon with the given name for (int i = 0; i < weaponCategory->GetNumItems(); i++) { CInventoryWeaponItemPtr weaponItem = boost::dynamic_pointer_cast<CInventoryWeaponItem>(weaponCategory->GetItem(i)); // Is this the right weapon? (must be a melee weapon, allowed empty) if (weaponItem != NULL && weaponItem->IsAllowedEmpty() && weaponItem->GetWeaponName() == weaponName) { DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("Entity %s is matching the melee weapon %s.\r", ent->name.c_str(), weaponName.c_str()); // Enable this weapon if (!gotFromShop) // grayman (#2376) { weaponItem->SetEnabled(true); } if (!ent->spawnArgs.GetBool("inv_map_start", "0") && !ent->spawnArgs.GetBool("inv_no_pickup_message", "0")) { NotifyOwnerAboutPickup( common->Translate( ent->spawnArgs.GetString("inv_name") ), weaponItem); } // We're done return weaponItem; } } DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("Couldn't find a match for weapon name: %s.\r", weaponName.c_str()); return CInventoryItemPtr(); }
void CDownloadMenu::StartDownload( idUserInterface *gui ) { // Add a new download for each selected mission const DownloadableModList &mods = gameLocal.m_MissionManager->GetDownloadableMods(); for( int i = 0; i < _selectedMods.Num(); ++i ) { int missionIndex = _selectedMods[i]; if( missionIndex > mods.Num() ) { continue; } const DownloadableMod &mod = *mods[missionIndex]; // The filename is deduced from the mod name found on the website idStr targetPath = g_Global.GetDarkmodPath().c_str(); targetPath += "/"; targetPath += cv_tdm_fm_path.GetString(); // Final path to the FM file idStr missionPath = targetPath + mod.modName + ".pk4"; DM_LOG( LC_MAINMENU, LT_INFO )LOGSTRING( "Will download the mission PK4 to %s (modName %s).", missionPath.c_str(), mod.modName.c_str() ); // log all the URLs for( int u = 0; u < mod.missionUrls.Num(); u++ ) { DM_LOG( LC_MAINMENU, LT_INFO )LOGSTRING( " URL: '%s'", mod.missionUrls[u].c_str() ); } CDownloadPtr download( new CDownload( mod.missionUrls, missionPath, true ) ); // gnartsch: In case only the language pack needs to be downloaded, do not add the mission itself to the download list. // In that case we did not add any urls for the mission itself anyway. int id = -1; if( mod.missionUrls.Num() > 0 ) { // Check for valid PK4 files after download id = gameLocal.m_DownloadManager->AddDownload( download ); } int l10nId = -1; // Check if there is a Localisation pack available if( mod.l10nPackUrls.Num() > 0 ) { DM_LOG( LC_MAINMENU, LT_INFO )LOGSTRING( "There are l10n pack URLs listed for this FM." ); for( int u = 0; u < mod.l10nPackUrls.Num(); u++ ) { DM_LOG( LC_MAINMENU, LT_INFO )LOGSTRING( " l10n pack URL: '%s'", mod.l10nPackUrls[u].c_str() ); } idStr l10nPackPath = targetPath + mod.modName + "_l10n.pk4"; DM_LOG( LC_MAINMENU, LT_INFO )LOGSTRING( "Will download the l10n pack to %s.", l10nPackPath.c_str() ); CDownloadPtr l10nDownload( new CDownload( mod.l10nPackUrls, l10nPackPath, true ) ); l10nId = gameLocal.m_DownloadManager->AddDownload( l10nDownload ); // Relate these two downloads, so that they might be handled as pair // gnartsch: In case only the language pack needs to be downloaded, we can ignore the mission itself if( id > 0 ) { download->SetRelatedDownloadId( l10nId ); } else { id = l10nId; l10nId = -1; } } // Store these IDs for later reference _downloads[missionIndex] = MissionDownload( id, l10nId ); } // Let the download manager start its downloads gameLocal.m_DownloadManager->ProcessDownloads(); }
void CInventoryItem::RestoreItemEntityFromDict(const idVec3& entPosition) { if (!m_ItemDict) { return; // no saved spawnargs, do nothing } // We have an item dictionary, let's respawn our entity idEntity* ent; // grayman #3723 - When restoring items this way, it's possible // that the name of the object we're about to restore is the same // as an object in the map. If so, change the name of the restored object. idStr error; const char *name; if ( (*m_ItemDict).GetString( "name", "", &name ) ) { sprintf( error, " on '%s'", name); } // check if this name is already in use if (gameLocal.FindEntity(name)) { gameLocal.Warning("Multiple entities named '%s'", name); DM_LOG(LC_INIT, LT_INIT)LOGSTRING("WARNING - Multiple entities named '%s'\r", name); // Rename with a unique name. (*m_ItemDict).Set("name",va("%s_%d",name,gameLocal.random.RandomInt(1000))); } if (!gameLocal.SpawnEntityDef(*m_ItemDict, &ent)) { DM_LOG(LC_INVENTORY, LT_ERROR)LOGSTRING("Can't respawn inventory item entity '%s'!\r", m_ItemDict->GetString("name")); gameLocal.Error("Can't respawn inventory item entity '%s'!", m_ItemDict->GetString("name")); } // Place the entity at the given position ent->SetOrigin(entPosition); // Hide the entity (don't delete it) CInventory::RemoveEntityFromMap(ent, false); // Set this as new item entity SetItemEntity(ent); // Finally, remove our saved spawnargs m_ItemDict.reset(); }
void CShop::AddPersistentStartingEquipment() { const CInventory &sourceInventory = *gameLocal.persistentPlayerInventory; // Cycle through all categories to add them for( int c = 0; c < sourceInventory.GetNumCategories(); ++c ) { const CInventoryCategoryPtr &category = sourceInventory.GetCategory( c ); for( int itemIdx = 0; itemIdx < category->GetNumItems(); ++itemIdx ) { const CInventoryItemPtr &item = category->GetItem( itemIdx ); if( item->GetPersistentCount() <= 0 ) { DM_LOG( LC_MAINMENU, LT_DEBUG )LOGSTRING( "Item %s is not marked as persistent, won't add to shop.\r", item->GetName().c_str() ); continue; // not marked as persistent } const idDict *itemDict = item->GetSavedItemEntityDict(); if( itemDict == NULL ) { DM_LOG( LC_MAINMENU, LT_WARNING )LOGSTRING( "Item %s is marked as persistent, but has no saved item dictionary.\r", item->GetName().c_str() ); continue; } idStr className = itemDict->GetString( "classname" ); // Try to look up the corresponding shop item definition for this item's classname CShopItemPtr found = FindShopItemDefByClassName( className ); if( found == NULL ) { DM_LOG( LC_MAINMENU, LT_DEBUG )LOGSTRING( "Can't find shopitem definition for classname %s, skipping.\r", className.c_str() ); continue; } int quantity = GetQuantityForItem( item ); // Don't attempt to merge if we don't have anything to merge in the first place if( quantity == 0 ) { DM_LOG( LC_MAINMENU, LT_DEBUG )LOGSTRING( "Persistent weapon doesn't have ammo, skipping.\r", className.c_str() ); continue; } // Check if this is a weapon CInventoryWeaponItemPtr weaponItem = boost::dynamic_pointer_cast<CInventoryWeaponItem>( item ); bool isWeapon = ( weaponItem != NULL ); bool weaponIsAllowedEmpty = weaponItem ? weaponItem->IsAllowedEmpty() : false; bool itemMerged = MergeIntoStartingEquipment( className, quantity, isWeapon, weaponIsAllowedEmpty ); // Append the item to the list if it didn't contribute quantity to // an existing list item. if( !itemMerged ) { CShopItemPtr anItem( new CShopItem( *found, quantity, 0, false ) ); bool canDrop = itemDict->GetBool( "inv_droppable", "1" ); anItem->SetCanDrop( canDrop ); _startingItems.Append( anItem ); } } } }
bool CMissionManager::DoRemoveFile(const fs::path& fileToRemove) { try { fs::remove(fileToRemove); DM_LOG(LC_MAINMENU, LT_DEBUG)LOGSTRING("Removed file in %s\r", fileToRemove.string().c_str()); return true; } catch (fs::filesystem_error& e) { DM_LOG(LC_MAINMENU, LT_DEBUG)LOGSTRING("Exception while removing file: %s\r", e.what()); return false; } }
ConversationStatePtr Conversation::GetConversationState( int actor ) { idAI *ai = GetActor( actor ); if( ai == NULL ) { DM_LOG( LC_CONVERSATION, LT_ERROR )LOGSTRING( "Conversation %s could not find actor.\r", _name.c_str() ); return ConversationStatePtr(); } // Let's see if the AI can handle this conversation command ConversationStatePtr convState = boost::dynamic_pointer_cast<ConversationState>( ai->GetMind()->GetState() ); if( convState == NULL ) { // AI is not in ConversationState anymore DM_LOG( LC_CONVERSATION, LT_DEBUG )LOGSTRING( "Conversation %s: ai %s is not in conversation mode anymore.\r", _name.c_str(), ai->name.c_str() ); return ConversationStatePtr(); } return convState; }
bool SingleBarkTask::Perform( Subsystem &subsystem ) { if( gameLocal.time < _barkStartTime ) { return false; // waiting for start delay to pass } // This task may not be performed with empty entity pointers idAI *owner = _owner.GetEntity(); assert( owner != NULL ); // If an endtime has been set, the bark is already playing if( _endTime > 0 ) { // Finish the task when the time is over return ( gameLocal.time >= _endTime ); } if( _soundName.IsEmpty() ) { DM_LOG( LC_AI, LT_ERROR )LOGSTRING( "SingleBarkTask has empty soundname, ending task.\r" ); return true; } // No end time set yet, emit our bark // grayman #2169 - no barks while underwater // grayman #3182 - no barks when an idle animation is playing and _allowDuringAnim == false // An idle animation that includes a voice frame command will have set // the wait state to 'idle'. An idle animation that has no voice frame // command will have set the wait state to 'idle_no_voice'. _barkLength = 0; bool canPlay = true; if( ( idStr( owner->WaitState() ) == "idle" ) && !_allowDuringAnim ) { // grayman #3182 canPlay = false; } if( canPlay && !owner->MouthIsUnderwater() ) { // grayman #3182 int msgTag = 0; // grayman #3355 // Push the message and play the sound if( _message != NULL ) { // Setup the message to be propagated, if we have one msgTag = gameLocal.GetNextMessageTag(); // grayman #3355 owner->AddMessage( _message, msgTag ); } owner->GetMind()->GetMemory().currentlyBarking = true; // grayman #3182 - idle anims w/voices cannot start // until this bark is finished _barkLength = owner->PlayAndLipSync( _soundName, "talk1", msgTag ); // grayman #3355 // Sanity check the returned length if( _barkLength == 0 ) { DM_LOG( LC_AI, LT_DEBUG )LOGSTRING( "Received 0 sound length when playing %s.\r", _soundName.c_str() ); } } _barkStartTime = gameLocal.time; _endTime = _barkStartTime + _barkLength; // End the task as soon as we've finished playing the sound return !IsBarking(); }
void CMultiStateMover::FindPositionEntities() { // Go through all the targets and find the PositionEntities for( int i = 0; i < targets.Num(); i++ ) { idEntity *target = targets[i].GetEntity(); if( !target->IsType( CMultiStateMoverPosition::Type ) ) { continue; } CMultiStateMoverPosition *moverPos = static_cast<CMultiStateMoverPosition *>( target ); DM_LOG( LC_ENTITY, LT_INFO )LOGSTRING( "Parsing multistate position entity %s.\r", moverPos->name.c_str() ); idStr positionName; if( !moverPos->spawnArgs.GetString( "position", "", positionName ) || positionName.IsEmpty() ) { gameLocal.Warning( "'position' spawnarg on %s is missing.", moverPos->name.c_str() ); continue; } if( GetPositionInfoIndex( positionName ) != -1 ) { gameLocal.Warning( "Multiple positions with name %s defined for %s.", positionName.c_str(), name.c_str() ); continue; } // greebo: Seems like the position entity is valid, let's build an info structure MoverPositionInfo info; info.positionEnt = moverPos; info.name = positionName; positionInfo.Append( info ); // Associate the mover position with this entity moverPos->SetMover( this ); } // Now remove all the MultiStatePositionInfo entities from the elevator targets // to avoid triggering of positionInfo entities when the elevator is reaching different floors. for( int i = 0; i < positionInfo.Num(); i++ ) { RemoveTarget( positionInfo[i].positionEnt.GetEntity() ); } }
bool CInventory::ReplaceItem(idEntity* oldItemEnt, idEntity* newItemEnt) { if (oldItemEnt == NULL) return false; idStr oldInvName = oldItemEnt->spawnArgs.GetString("inv_name"); CInventoryItemPtr oldItem = GetItem(oldInvName); if (oldItem == NULL) { gameLocal.Warning("Could not find old inventory item for %s", oldItemEnt->name.c_str()); DM_LOG(LC_INVENTORY, LT_DEBUG)LOGSTRING("Could not find old inventory item for %s\n", oldItemEnt->name.c_str()); return false; } // greebo: Let's call PutItem on the new entity first to see what kind of item this is // PutItem will also take care of the mission data callbacks for the objectives CInventoryItemPtr newItem = PutItem(newItemEnt, m_Owner.GetEntity()); if (newItem != NULL && newItem->Category() == oldItem->Category()) { // New item has been added, swap the old and the new one to fulfil the inventory position guarantee oldItem->Category()->SwapItemPosition(oldItem, newItem); } // If SwapItemPosition has been called, newItem now takes the place of oldItem before the operation. // Remove the old item in any case, but only if the items are actually different. // In case anybody wonder, newItem might be the same as oldItem in the case of stackable items or loot. if (oldItem != newItem) { RemoveItem(oldItem); } return 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 ); // 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 MoveToPositionTask::Perform( Subsystem &subsystem ) { DM_LOG( LC_AI, LT_INFO )LOGSTRING( "MoveToPositionTask performing.\r" ); idAI *owner = _owner.GetEntity(); // This task may not be performed with empty entity pointer assert( owner != NULL ); // Check for target refinements UpdateTargetPosition( owner ); // Has the target position changed since the last run if( _prevTargetPosition != _targetPosition ) { // Yes, move towards this new position if( !owner->MoveToPosition( _targetPosition, _accuracy ) ) { // Destination unreachable, end task return true; } } // Remember this target _prevTargetPosition = _targetPosition; if( owner->AI_MOVE_DONE ) { // Position reached, turn to the given yaw, if valid if( _targetYaw != idMath::INFINITY ) { owner->TurnToward( _targetYaw ); } return true; } return false; // not finished yet }
void CFrobLock::AutoSetupLockHandles() { // Find a suitable teamchain member idEntity* part = FindMatchingTeamEntity(CFrobLockHandle::Type); while (part != NULL) { // Found the handle, set it up AddLockHandle(static_cast<CFrobLockHandle*>(part)); DM_LOG(LC_ENTITY, LT_INFO)LOGSTRING("%s: Auto-added lock handle %s to local list.\r", name.c_str(), part->name.c_str()); // Get the next handle part = FindMatchingTeamEntity(CFrobLockHandle::Type, part); } for (int i = 0; i < m_Lockhandles.Num(); i++) { CFrobLockHandle* handle = m_Lockhandles[i].GetEntity(); if (handle == NULL) continue; // The first handle is the master, all others get their master flag set to FALSE handle->SetMasterHandle(i == 0); } }
void CFrobLock::PostSpawn() { idStr lockHandleName = spawnArgs.GetString("lock_handle", ""); if (!lockHandleName.IsEmpty()) { idEntity* handleEnt = gameLocal.FindEntity(lockHandleName); if (handleEnt != NULL && handleEnt->IsType(CFrobLockHandle::Type)) { // Convert to froblockHandle pointer and call the helper function CFrobLockHandle* handle = static_cast<CFrobLockHandle*>(handleEnt); AddLockHandle(handle); // Check if we should bind the named handle to ourselves if (spawnArgs.GetBool("lock_handle_bind_flag", "1")) { handle->Bind(this, true); } } else { DM_LOG(LC_LOCKPICK, LT_ERROR)LOGSTRING("lockHandle entity not spawned or of wrong type: %s\r", lockHandleName.c_str()); } } // greebo: Should we auto-setup the lockHandles? if (spawnArgs.GetBool("auto_setup_lock_handles", "1")) { AutoSetupLockHandles(); } }
CStimPtr CStimResponseCollection::AddStim( idEntity *Owner, int Type, float fRadius, bool bRemovable, bool bDefault ) { CStimPtr stim; int i, n; n = m_Stims.Num(); for( i = 0; i < n; i++ ) { if( m_Stims[i]->m_StimTypeId == Type ) { DM_LOG( LC_STIM_RESPONSE, LT_DEBUG )LOGSTRING( "Stim of that type is already in collection, returning it.\r" ); stim = m_Stims[i]; break; } } if( stim == NULL ) { // Create either type specific descended class, or the default base class stim = CreateStim( Owner, ( StimType ) Type ); if( stim != NULL ) { // grayman #2862 m_Stims.Append( stim ); } } if( stim != NULL ) { stim->m_Default = bDefault; stim->m_Removable = bRemovable; stim->m_Radius = fRadius; stim->m_State = SS_DISABLED; gameLocal.AddStim( Owner ); } return stim; }
bool Mind::EndState() { if (!_stateQueue.empty()) { // Don't destroy the State object this round _recycleBin = _stateQueue.front(); DM_LOG(LC_AI, LT_INFO)LOGSTRING("Ending State %s (%s)\r", _recycleBin->GetName().c_str(), _owner.GetEntity()->name.c_str()); // Remove the current state from the queue _stateQueue.pop_front(); // Trigger a stateswitch next round in any case _switchState = true; } if (_stateQueue.empty()) { // No states left, add the default state at least PushState(STATE_DEFAULT); } // Return TRUE if there are additional states left return true; }
void PainState::Init( idAI *owner ) { // Init base class first State::Init( owner ); DM_LOG( LC_AI, LT_INFO )LOGSTRING( "PainState initialised.\r" ); assert( owner ); // grayman #3424 - if already playing a pain anim, skip this one if( idStr( owner->WaitState( ANIMCHANNEL_TORSO ) ) == "pain" ) { return; } Memory &memory = owner->GetMemory(); // Play the animation owner->SetAnimState( ANIMCHANNEL_TORSO, "Torso_Pain", 4 ); owner->SetAnimState( ANIMCHANNEL_LEGS, "Legs_Pain", 4 ); owner->SetWaitState( ANIMCHANNEL_TORSO, "pain" ); owner->SetWaitState( ANIMCHANNEL_LEGS, "pain" ); // Set end time _stateEndTime = gameLocal.time + 5000; // grayman #3140 - if drowning, skip issuing a message. The drowning // sound effect is handled in idActor::Damage(). if( memory.causeOfPain != EPC_Drown ) { memory.alertPos = owner->GetPhysics()->GetOrigin(); // Do a single bark and assemble an AI message CommMessagePtr message = CommMessagePtr( new CommMessage( CommMessage::DetectedEnemy_CommType, owner, NULL, // from this AI to anyone NULL, memory.alertPos, 0 ) ); owner->commSubsystem->AddCommTask( CommunicationTaskPtr( new SingleBarkTask( "snd_pain_large", message ) ) ); if( cv_ai_debug_transition_barks.GetBool() ) { gameLocal.Printf( "%d: %s is hurt, barks 'snd_pain_large'\n", gameLocal.time, owner->GetName() ); } } }