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;
}
Exemple #15
0
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();
}
Exemple #17
0
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;
	}
}
Exemple #20
0
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() );
	}
}
Exemple #23
0
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;
}
Exemple #24
0
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;
}
Exemple #25
0
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;
}
Exemple #29
0
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;
}
Exemple #30
0
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() );
		}
	}
}