/* ================ idBrittleFracture::Spawn ================ */ void idBrittleFracture::Spawn() { // get shard properties decalMaterial = declManager->FindMaterial( spawnArgs.GetString( "mtr_decal" ) ); decalSize = spawnArgs.GetFloat( "decalSize", "40" ); maxShardArea = spawnArgs.GetFloat( "maxShardArea", "200" ) * 2.0f ; maxShardArea = idMath::ClampFloat( 100, 10000, maxShardArea ); maxShatterRadius = spawnArgs.GetFloat( "maxShatterRadius", "40" ); minShatterRadius = spawnArgs.GetFloat( "minShatterRadius", "10" ); linearVelocityScale = spawnArgs.GetFloat( "linearVelocityScale", "0.1" ); angularVelocityScale = spawnArgs.GetFloat( "angularVelocityScale", "40" ); fxFracture = spawnArgs.GetString( "fx" ); // make sure that max is greater than min ( otherwise negative number square root happens ) if( maxShatterRadius < minShatterRadius ) { idLib::Warning( "BrittleFracture, minShatterRadius(%2f) is greater than maxShatterRadius(%2f). Unknown results will ensue.", minShatterRadius, maxShatterRadius ); } // get rigid body properties shardMass = spawnArgs.GetFloat( "shardMass", "20" ); shardMass = idMath::ClampFloat( 0.001f, 1000.0f, shardMass ); spawnArgs.GetFloat( "density", "0.1", density ); density = idMath::ClampFloat( 0.001f, 1000.0f, density ); spawnArgs.GetFloat( "friction", "0.4", friction ); friction = idMath::ClampFloat( 0.0f, 1.0f, friction ); spawnArgs.GetFloat( "bouncyness", "0.01", bouncyness ); bouncyness = idMath::ClampFloat( 0.0f, 1.0f, bouncyness ); disableFracture = spawnArgs.GetBool( "disableFracture", "0" ); health = spawnArgs.GetInt( "health", "40" ); fl.takedamage = true; // FIXME: set "bleed" so idProjectile calls AddDamageEffect spawnArgs.SetBool( "bleed", 1 ); // check for xray surface if( renderEntity.hModel != NULL ) { const idRenderModel* model = renderEntity.hModel; isXraySurface = false; for( int i = 0; i < model->NumSurfaces(); i++ ) { const modelSurface_t* surf = model->Surface( i ); if( idStr( surf->shader->GetName() ) == "textures/smf/window_scratch" ) { isXraySurface = true; break; } } } CreateFractures( renderEntity.hModel ); FindNeighbours(); defaultRenderModel = renderEntity.hModel; renderEntity.hModel = renderModelManager->AllocModel(); renderEntity.hModel->InitEmpty( brittleFracture_SnapshotName ); renderEntity.callback = idBrittleFracture::ModelCallback; renderEntity.noShadow = true; renderEntity.noSelfShadow = true; renderEntity.noDynamicInteractions = false; }
void CMissionManager::OnMissionComplete() { CModInfoPtr info = GetCurrentModInfo(); if (info == NULL) { DM_LOG(LC_MAINMENU, LT_ERROR)LOGSTRING("Could not find mission info for current mod.\r"); return; } // Ensure that this was the last mission if in campaign mode, otherwise ignore this call if (CurrentModIsCampaign()) { if (_curMissionIndex == -1) { gameLocal.Error("Invalid mission index in OnMissionComplete()"); } if (_curMissionIndex < _mapSequence.Num() - 1) { // This is not yet the last mission in the campaign, ignore this call return; } } // Mark the current difficulty level as completed info->SetKeyValue(va("mission_completed_%d", gameLocal.m_DifficultyManager.GetDifficultyLevel()), "1"); idPlayer* player = gameLocal.GetLocalPlayer(); if (player != NULL) { int gold, jewelry, goods; int total = player->Inventory()->GetLoot(gold, jewelry, goods); info->SetKeyValue(va("mission_loot_collected_%d", gameLocal.m_DifficultyManager.GetDifficultyLevel()), idStr(total)); } }
idStr CMissionManager::GetCurrentModName() { CModInfoPtr info = GetCurrentModInfo(); return (info != NULL) ? idStr( common->Translate( info->modName ) ) : ""; }
/* ============ RunAASDir_f ============ */ void RunAASDir_f( const idCmdArgs& args ) { int i; idAASBuild aas; idAASSettings settings; idFileList* mapFiles; if( args.Argc() <= 1 ) { common->Printf( "runAASDir <folder>\n" ); return; } common->ClearWarnings( "compiling AAS" ); common->SetRefreshOnPrint( true ); // get the aas settings definitions const idDict* dict = gameEdit->FindEntityDefDict( "aas_types", false ); if( !dict ) { common->Error( "Unable to find entityDef for 'aas_types'" ); } // scan for .map files mapFiles = fileSystem->ListFiles( idStr( "maps/" ) + args.Argv( 1 ), ".map" ); // create AAS files for all the .map files for( i = 0; i < mapFiles->GetNumFiles(); i++ ) { if( i ) { common->Printf( "=======================================================\n" ); } const idKeyValue* kv = dict->MatchPrefix( "type" ); while( kv != NULL ) { const idDict* settingsDict = gameEdit->FindEntityDefDict( kv->GetValue(), false ); if( !settingsDict ) { common->Warning( "Unable to find '%s' in def/aas.def", kv->GetValue().c_str() ); } else { settings.FromDict( kv->GetValue(), settingsDict ); aas.Build( idStr( "maps/" ) + args.Argv( 1 ) + "/" + mapFiles->GetFile( i ), &settings ); } kv = dict->MatchPrefix( "type", kv ); if( kv ) { common->Printf( "=======================================================\n" ); } } } fileSystem->FreeFileList( mapFiles ); common->SetRefreshOnPrint( false ); common->PrintWarnings(); }
void CShop::AddMapItems( idMapFile *mapFile ) { // get the difficulty level idStr diffString = "diff_" + idStr( gameLocal.m_DifficultyManager.GetDifficultyLevel() ) + "_nospawn"; // Cycle through map entities. Since the number of entities can change in the loop, // always refresh the entity count used to terminate the loop. // Skip entity 0, which is the world. for( int i = 1; i < mapFile->GetNumEntities(); i++ ) { idMapEntity *mapEnt = mapFile->GetEntity( i ); // does this entity have an inv_map_start spawnflag set to 1? if( mapEnt->epairs.GetBool( "inv_map_start", "0" ) ) { // does this entity exist in the chosen difficulty level? if( idStr::Icmp( mapEnt->epairs.GetString( diffString, "0" ), "0" ) == 0 ) { idStr className = mapEnt->epairs.GetString( "classname" ); int quantity; bool isWeapon = false; // is this an arrow? int max_ammo = 1; // in case this is a weapon // Special handling for arrows. The shop definitions allow for // atdm:weapon_*, but not atdm:ammo_*. The latter form is used on // map entities. If this is an atdm:ammo_* entity, change its ID (itemName) // to the allowable atdm:weapon_* form. if( className.Find( "atdm:ammo_" ) >= 0 ) { isWeapon = true; className.Replace( "atdm:ammo_", "atdm:weapon_" ); // An arrow's quantity is defined by "inv_ammo_amount" instead // of "inv_count". Look for that. quantity = mapEnt->epairs.GetInt( "inv_ammo_amount", "0" ); // Arrow quantities have limits. See if you can find the limit // for this weapon. if( quantity > 0 ) { max_ammo = GetMaxAmmo( className ); quantity = ( quantity > max_ammo ) ? max_ammo : quantity; } } else { quantity = mapEnt->epairs.GetInt( "inv_count", "1" ); } if( quantity > 0 ) { CShopItemPtr found = FindShopItemDefByClassName( className ); if( found != NULL ) { // We don't have much info about the weapon item at this point and FindEntityDefDict() is lagging // so let's assume there is only a shortsword and blackjack as possible melee items for now bool isMeleeWeapon = ( className.Cmp( "atdm:weapon_shortsword" ) == 0 || className.Cmp( "atdm:weapon_blackjack" ) == 0 ); // If this item is stackable, and already exists in the _startingItems list, // bump up the quantity there instead of appending the item to the list. // If the item is not stackable, and we already have it, ignore it. bool itemMerged = MergeIntoStartingEquipment( className, quantity, isWeapon, isMeleeWeapon ); // 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 = mapEnt->epairs.GetBool( "inv_droppable", "1" ); anItem->SetCanDrop( canDrop ); _startingItems.Append( anItem ); } } else { gameLocal.Warning( "Map entity is not a valid shop item: %s", className.c_str() ); } } } } } }
void CDownloadMenu::ShowDownloadResult( idUserInterface *gui ) { // greebo: Let the mod list be refreshed // We need the information from darkmod.txt later down this road gameLocal.m_MissionManager->ReloadModList(); int successfulDownloads = 0; int failedDownloads = 0; const DownloadableModList &mods = gameLocal.m_MissionManager->GetDownloadableMods(); for( ActiveDownloads::iterator i = _downloads.begin(); i != _downloads.end(); ++i ) { CDownloadPtr download = gameLocal.m_DownloadManager->GetDownload( i->second.missionDownloadId ); if( download == NULL ) { continue; } if( i->first > mods.Num() ) { continue; } const DownloadableMod &mod = *mods[i->first]; switch( download->GetStatus() ) { case CDownload::NOT_STARTED_YET: gameLocal.Warning( "Some downloads haven't been processed?" ); break; case CDownload::FAILED: failedDownloads++; break; case CDownload::IN_PROGRESS: gameLocal.Warning( "Some downloads still in progress?" ); break; case CDownload::SUCCESS: { // gnartsch bool l10nPackDownloaded = false; // In case of success, check l10n download status if( i->second.l10nPackDownloadId != -1 ) { CDownloadPtr l10nDownload = gameLocal.m_DownloadManager->GetDownload( i->second.l10nPackDownloadId ); CDownload::DownloadStatus l10nStatus = l10nDownload->GetStatus(); if( l10nStatus == CDownload::NOT_STARTED_YET || l10nStatus == CDownload::IN_PROGRESS ) { gameLocal.Warning( "Localisation pack download not started or still in progress?" ); } else if( l10nStatus == CDownload::FAILED ) { gameLocal.Warning( "Failed to download localisation pack!" ); // Turn this download into a failed one failedDownloads++; } else if( l10nStatus == CDownload::SUCCESS ) { // both successfully downloaded successfulDownloads++; // gnartsch l10nPackDownloaded = true; } } else { // regular download without l10n ... or l10n download only (gnartsch) successfulDownloads++; // gnartsch: Consider Localization pack having been dealt with as well l10nPackDownloaded = true; } // Save the mission version into the MissionDB for later use CModInfoPtr missionInfo = gameLocal.m_MissionManager->GetModInfo( mod.modName ); missionInfo->SetKeyValue( "downloaded_version", idStr( mod.version ).c_str() ); // gnartsch: Mark l10n pack as present, so that the mission may disappear from the list of 'Available Downloads' missionInfo->isL10NpackInstalled = l10nPackDownloaded; } break; }; } gameLocal.Printf( "Successful downloads: %d\nFailed downloads: %d\n", successfulDownloads, failedDownloads ); // Display the popup box GuiMessage msg; msg.type = GuiMessage::MSG_OK; msg.okCmd = "close_msg_box;onDownloadCompleteConfirm"; msg.title = common->Translate( "#str_02142" ); // "Mission Download Result" msg.message = ""; if( successfulDownloads > 0 ) { msg.message += va( // "%d mission/missions successfully downloaded. You'll find it/them in the 'New Mission' page." GetPlural( successfulDownloads, common->Translate( "#str_02144" ), common->Translate( "#str_02145" ) ), successfulDownloads ); } if( failedDownloads > 0 ) { // "\n%d mission(s) couldn't be downloaded. Please check your disk space (or maybe some file is write protected) and try again." msg.message += va( common->Translate( "#str_02146" ), failedDownloads ); } gameLocal.AddMainMenuMessage( msg ); // Remove all downloads for( ActiveDownloads::iterator i = _downloads.begin(); i != _downloads.end(); ++i ) { gameLocal.m_DownloadManager->RemoveDownload( i->second.missionDownloadId ); if( i->second.l10nPackDownloadId != -1 ) { gameLocal.m_DownloadManager->RemoveDownload( i->second.l10nPackDownloadId ); } } _downloads.clear(); }
/* ======================== idMenuScreen_Shell_SystemOptions::HideScreen ======================== */ void idMenuScreen_Shell_SystemOptions::HideScreen( const mainMenuTransition_t transitionType ) { if ( systemData.IsRestartRequired() ) { class idSWFScriptFunction_Restart : public idSWFScriptFunction_RefCounted { public: idSWFScriptFunction_Restart( gameDialogMessages_t _msg, bool _restart ) { msg = _msg; restart = _restart; } idSWFScriptVar Call( idSWFScriptObject * thisObject, const idSWFParmList & parms ) { common->Dialog().ClearDialog( msg ); if ( restart ) { idStr cmdLine = Sys_GetCmdLine(); if ( cmdLine.Find( "com_skipIntroVideos" ) < 0 ) { cmdLine.Append( " +set com_skipIntroVideos 1" ); } Sys_ReLaunch( (void*)cmdLine.c_str(), cmdLine.Length() ); } return idSWFScriptVar(); } private: gameDialogMessages_t msg; bool restart; }; idStaticList<idSWFScriptFunction *, 4> callbacks; idStaticList<idStrId, 4> optionText; callbacks.Append( new idSWFScriptFunction_Restart( GDM_GAME_RESTART_REQUIRED, false ) ); callbacks.Append( new idSWFScriptFunction_Restart( GDM_GAME_RESTART_REQUIRED, true ) ); optionText.Append( idStrId( "#str_00100113" ) ); // Continue optionText.Append( idStrId( "#str_02487" ) ); // Restart Now common->Dialog().AddDynamicDialog( GDM_GAME_RESTART_REQUIRED, callbacks, optionText, true, idStr() ); } if ( systemData.IsDataChanged() ) { systemData.CommitData(); } idMenuScreen::HideScreen( transitionType ); }
/* ============ idInternalCVar::InternalSetInteger ============ */ void idInternalCVar::InternalSetInteger( const int newValue ) { Set( idStr( newValue ), true, false ); }
/* ============ idInternalCVar::InternalSetFloat ============ */ void idInternalCVar::InternalSetFloat( const float newValue ) { Set( idStr( newValue ), true, false ); }
/* ============ idInternalCVar::UpdateValue ============ */ void idInternalCVar::UpdateValue( void ) { bool clamped = false; if ( flags & CVAR_BOOL ) { integerValue = ( atoi( value ) != 0 ); floatValue = integerValue; if ( idStr::Icmp( value, "0" ) != 0 && idStr::Icmp( value, "1" ) != 0 ) { valueString = idStr( (bool)( integerValue != 0 ) ); value = valueString.c_str(); } } else if ( flags & CVAR_INTEGER ) { integerValue = (int)atoi( value ); if ( valueMin < valueMax ) { if ( integerValue < valueMin ) { integerValue = (int)valueMin; clamped = true; } else if ( integerValue > valueMax ) { integerValue = (int)valueMax; clamped = true; } } if ( clamped || !idStr::IsNumeric( value ) || idStr::FindChar( value, '.' ) ) { valueString = idStr( integerValue ); value = valueString.c_str(); } floatValue = (float)integerValue; } else if ( flags & CVAR_FLOAT ) { floatValue = (float)atof( value ); if ( valueMin < valueMax ) { if ( floatValue < valueMin ) { floatValue = valueMin; clamped = true; } else if ( floatValue > valueMax ) { floatValue = valueMax; clamped = true; } } if ( clamped || !idStr::IsNumeric( value ) ) { valueString = idStr( floatValue ); value = valueString.c_str(); } integerValue = (int)floatValue; } else { if ( valueStrings && valueStrings[0] ) { integerValue = 0; for ( int i = 0; valueStrings[i]; i++ ) { if ( valueString.Icmp( valueStrings[i] ) == 0 ) { integerValue = i; break; } } valueString = valueStrings[integerValue]; value = valueString.c_str(); floatValue = (float)integerValue; } else if ( valueString.Length() < 32 ) { floatValue = (float)atof( value ); integerValue = (int)floatValue; } else { floatValue = 0.0f; integerValue = 0; } } }
/* ============ idInternalCVar::InternalSetBool ============ */ void idInternalCVar::InternalSetBool( const bool newValue ) { Set( idStr( newValue ), true, false ); }
void idCVarSystemLocal::ListByFlags( const idCmdArgs &args, cvarFlags_t flags ) { int i, argNum; idStr match, indent, string; const idInternalCVar *cvar; idList<const idInternalCVar *>cvarList; enum { SHOW_VALUE, SHOW_DESCRIPTION, SHOW_TYPE, SHOW_FLAGS } show; argNum = 1; show = SHOW_VALUE; if ( idStr::Icmp( args.Argv( argNum ), "-" ) == 0 || idStr::Icmp( args.Argv( argNum ), "/" ) == 0 ) { if ( idStr::Icmp( args.Argv( argNum + 1 ), "help" ) == 0 || idStr::Icmp( args.Argv( argNum + 1 ), "?" ) == 0 ) { argNum = 3; show = SHOW_DESCRIPTION; } else if ( idStr::Icmp( args.Argv( argNum + 1 ), "type" ) == 0 || idStr::Icmp( args.Argv( argNum + 1 ), "range" ) == 0 ) { argNum = 3; show = SHOW_TYPE; } else if ( idStr::Icmp( args.Argv( argNum + 1 ), "flags" ) == 0 ) { argNum = 3; show = SHOW_FLAGS; } } if ( args.Argc() > argNum ) { match = args.Args( argNum, -1 ); match.Replace( " ", "" ); } else { match = ""; } for ( i = 0; i < localCVarSystem.cvars.Num(); i++ ) { cvar = localCVarSystem.cvars[i]; if ( !( cvar->GetFlags() & flags ) ) { continue; } if ( match.Length() && !cvar->nameString.Filter( match, false ) ) { continue; } cvarList.Append( cvar ); } cvarList.Sort(); switch( show ) { case SHOW_VALUE: { for ( i = 0; i < cvarList.Num(); i++ ) { cvar = cvarList[i]; common->Printf( FORMAT_STRING S_COLOR_WHITE "\"%s\"\n", cvar->nameString.c_str(), cvar->valueString.c_str() ); } break; } case SHOW_DESCRIPTION: { indent.Fill( ' ', NUM_NAME_CHARS ); indent.Insert( "\n", 0 ); for ( i = 0; i < cvarList.Num(); i++ ) { cvar = cvarList[i]; common->Printf( FORMAT_STRING S_COLOR_WHITE "%s\n", cvar->nameString.c_str(), CreateColumn( cvar->GetDescription(), NUM_DESCRIPTION_CHARS, indent, string ) ); } break; } case SHOW_TYPE: { for ( i = 0; i < cvarList.Num(); i++ ) { cvar = cvarList[i]; if ( cvar->GetFlags() & CVAR_BOOL ) { common->Printf( FORMAT_STRING S_COLOR_CYAN "bool\n", cvar->GetName() ); } else if ( cvar->GetFlags() & CVAR_INTEGER ) { if ( cvar->GetMinValue() < cvar->GetMaxValue() ) { common->Printf( FORMAT_STRING S_COLOR_GREEN "int " S_COLOR_WHITE "[%d, %d]\n", cvar->GetName(), (int) cvar->GetMinValue(), (int) cvar->GetMaxValue() ); } else { common->Printf( FORMAT_STRING S_COLOR_GREEN "int\n", cvar->GetName() ); } } else if ( cvar->GetFlags() & CVAR_FLOAT ) { if ( cvar->GetMinValue() < cvar->GetMaxValue() ) { common->Printf( FORMAT_STRING S_COLOR_RED "float " S_COLOR_WHITE "[%s, %s]\n", cvar->GetName(), idStr( cvar->GetMinValue() ).c_str(), idStr( cvar->GetMaxValue() ).c_str() ); } else { common->Printf( FORMAT_STRING S_COLOR_RED "float\n", cvar->GetName() ); } } else if ( cvar->GetValueStrings() ) { common->Printf( FORMAT_STRING S_COLOR_WHITE "string " S_COLOR_WHITE "[", cvar->GetName() ); for ( int j = 0; cvar->GetValueStrings()[j] != NULL; j++ ) { if ( j ) { common->Printf( S_COLOR_WHITE ", %s", cvar->GetValueStrings()[j] ); } else { common->Printf( S_COLOR_WHITE "%s", cvar->GetValueStrings()[j] ); } } common->Printf( S_COLOR_WHITE "]\n" ); } else { common->Printf( FORMAT_STRING S_COLOR_WHITE "string\n", cvar->GetName() ); } } break; } case SHOW_FLAGS: { for ( i = 0; i < cvarList.Num(); i++ ) { cvar = cvarList[i]; common->Printf( FORMAT_STRING, cvar->GetName() ); string = ""; if ( cvar->GetFlags() & CVAR_BOOL ) { string += S_COLOR_CYAN "B "; } else if ( cvar->GetFlags() & CVAR_INTEGER ) { string += S_COLOR_GREEN "I "; } else if ( cvar->GetFlags() & CVAR_FLOAT ) { string += S_COLOR_RED "F "; } else { string += S_COLOR_WHITE "S "; } if ( cvar->GetFlags() & CVAR_SYSTEM ) { string += S_COLOR_WHITE "SYS "; } else if ( cvar->GetFlags() & CVAR_RENDERER ) { string += S_COLOR_WHITE "RNDR "; } else if ( cvar->GetFlags() & CVAR_SOUND ) { string += S_COLOR_WHITE "SND "; } else if ( cvar->GetFlags() & CVAR_GUI ) { string += S_COLOR_WHITE "GUI "; } else if ( cvar->GetFlags() & CVAR_GAME ) { string += S_COLOR_WHITE "GAME "; } else if ( cvar->GetFlags() & CVAR_TOOL ) { string += S_COLOR_WHITE "TOOL "; } else { string += S_COLOR_WHITE " "; } string += ( cvar->GetFlags() & CVAR_USERINFO ) ? "UI " : " "; string += ( cvar->GetFlags() & CVAR_SERVERINFO ) ? "SI " : " "; string += ( cvar->GetFlags() & CVAR_STATIC ) ? "ST " : " "; string += ( cvar->GetFlags() & CVAR_CHEAT ) ? "CH " : " "; string += ( cvar->GetFlags() & CVAR_INIT ) ? "IN " : " "; string += ( cvar->GetFlags() & CVAR_ROM ) ? "RO " : " "; string += ( cvar->GetFlags() & CVAR_ARCHIVE ) ? "AR " : " "; string += ( cvar->GetFlags() & CVAR_MODIFIED ) ? "MO " : " "; string += "\n"; common->Printf( string ); } break; } } common->Printf( "\n%i cvars listed\n\n", cvarList.Num() ); common->Printf( "listCvar [search string] = list cvar values\n" "listCvar -help [search string] = list cvar descriptions\n" "listCvar -type [search string] = list cvar types\n" "listCvar -flags [search string] = list cvar flags\n" ); }
/* ============ idCVarSystemLocal::Toggle_f ============ */ void idCVarSystemLocal::Toggle_f( const idCmdArgs &args ) { int argc, i; float current, set; const char *text; argc = args.Argc(); if ( argc < 2 ) { common->Printf ("usage:\n" " toggle <variable> - toggles between 0 and 1\n" " toggle <variable> <value> - toggles between 0 and <value>\n" " toggle <variable> [string 1] [string 2]...[string n] - cycles through all strings\n"); return; } idInternalCVar *cvar = localCVarSystem.FindInternal( args.Argv( 1 ) ); if ( cvar == NULL ) { common->Warning( "Toggle_f: cvar \"%s\" not found", args.Argv( 1 ) ); return; } if ( argc > 3 ) { // cycle through multiple values text = cvar->GetString(); for( i = 2; i < argc; i++ ) { if ( !idStr::Icmp( text, args.Argv( i ) ) ) { // point to next value i++; break; } } if ( i >= argc ) { i = 2; } common->Printf( "set %s = %s\n", args.Argv(1), args.Argv( i ) ); cvar->Set( va("%s", args.Argv( i ) ), false, false ); } else { // toggle between 0 and 1 current = cvar->GetFloat(); if ( argc == 3 ) { set = atof( args.Argv( 2 ) ); } else { set = 1.0f; } if ( current == 0.0f ) { current = set; } else { current = 0.0f; } common->Printf( "set %s = %f\n", args.Argv(1), current ); cvar->Set( idStr( current ), false, false ); } }
void CShop::UpdateGUI( idUserInterface *gui ) { gui->SetStateInt( "gold", _gold ); gui->SetStateInt( "forSaleMoreVisible", _itemsForSale.Num() > LIST_SIZE_FOR_SALE ); gui->SetStateInt( "purchasedMoreVisible", _itemsPurchased.Num() > LIST_SIZE_PURCHASED ); gui->SetStateInt( "startingMoreVisible", _startingItems.Num() > LIST_SIZE_STARTING ); if( GetNothingForSale() ) { // nothing for sale, let the user know gui->SetStateInt( "forSaleAvail0", 0 ); gui->SetStateString( "forSale0_name", common->Translate( "#str_02314" ) ); // "<no items for sale>" // Tels: Fix #2661: do not show a description if nothing is for sale gui->SetStateString( "gui::forSale0_desc", "" ); gui->SetStateString( "gui::forSale0_image", "" ); gui->SetStateString( "forSaleCost0_cost", "0" ); // Clear out the rest of the GUI for( int i = 1; i < LIST_SIZE_FOR_SALE; i++ ) { gui->SetStateString( va( "forSaleCost%d_cost", i ), "" ); gui->SetStateInt( va( "forSaleAvail%d", i ), 0 ); gui->SetStateString( va( "forSale%d_name", i ), "" ); gui->SetStateString( va( "forSale%d_desc", i ), "" ); gui->SetStateString( va( "forSale%d_image", i ), "" ); } } else { for( int i = 0; i < LIST_SIZE_FOR_SALE; i++ ) { idStr guiCost = idStr( "forSaleCost" ) + i + "_cost"; idStr guiName = idStr( "forSale" ) + i + "_name"; idStr guiDesc = idStr( "forSale" ) + i + "_desc"; idStr guiImage = idStr( "forSale" ) + i + "_image"; idStr guiAvailable = idStr( "forSaleAvail" ) + i; idStr name = idStr( "" ); idStr desc = idStr( "" ); idStr image = idStr( "" ); idStr cost = idStr( "" ); int available = 0; if( _forSaleTop + i < _itemsForSale.Num() ) { const CShopItemPtr &item = _itemsForSale[_forSaleTop + i]; name = item->GetName() + " (" + item->GetCount() + ")"; desc = item->GetName() + ": " + item->GetDescription(); image = item->GetImage(); available = item->GetCost() <= _gold ? item->GetCount() : 0; cost = idStr( item->GetCost() ) + " GP "; } gui->SetStateString( guiCost, cost ); gui->SetStateInt( guiAvailable, available ); gui->SetStateString( guiName, name ); gui->SetStateString( guiDesc, desc ); gui->SetStateString( guiImage, image ); } } for( int i = 0; i < LIST_SIZE_PURCHASED; i++ ) { idStr guiCost = idStr( "boughtCost" ) + i + "_cost"; idStr guiName = idStr( "bought" ) + i + "_name"; idStr guiDesc = idStr( "bought" ) + i + "_desc"; idStr guiImage = idStr( "bought" ) + i + "_image"; idStr guiAvailable = idStr( "boughtAvail" ) + i; idStr name = idStr( "" ); idStr desc = idStr( "" ); idStr image = idStr( "" ); idStr cost = idStr( "" ); int available = 0; if( _purchasedTop + i < _itemsPurchased.Num() ) { const CShopItemPtr &item = _itemsPurchased[_purchasedTop + i]; name = item->GetName() + " (" + item->GetCount() + ")"; desc = item->GetName() + ": " + item->GetDescription(); image = item->GetImage(); available = 1; // sell item is always available cost = idStr( item->GetCost() ) + " GP "; } gui->SetStateString( guiCost, cost ); gui->SetStateInt( guiAvailable, available ); gui->SetStateString( guiName, name ); gui->SetStateString( guiDesc, desc ); gui->SetStateString( guiImage, image ); } for( int i = 0; i < LIST_SIZE_STARTING; i++ ) { idStr guiName = idStr( "starting" ) + i + "_name"; idStr guiDesc = idStr( "starting" ) + i + "_desc"; idStr guiImage = idStr( "starting" ) + i + "_image"; idStr guiAvailable = idStr( "startingAvail" ) + i; // Tels: if the item can be dropped or undropped, this is 1 idStr guiDrop = idStr( "dropVisible" ) + i; idStr name = idStr( "" ); idStr desc = idStr( "" ); idStr image = idStr( "" ); int available = 0; bool dropVisible = false; if( _startingTop + i < _startingItems.Num() ) { const CShopItemPtr &item = _startingItems[_startingTop + i]; name = item->GetName() + " (" + item->GetCount() + ")"; desc = item->GetName() + ": " + item->GetDescription(); image = item->GetImage(); // Tels: Fix #2563 (startingItems can always be dropped, regardless of how much gold you have) // available = item->GetCost() <= gold ? item->GetCount() : 0; available = item->GetCount(); dropVisible = item->GetCanDrop(); } gui->SetStateBool( guiDrop, dropVisible ); gui->SetStateInt( guiAvailable, available ); gui->SetStateString( guiName, name ); gui->SetStateString( guiDesc, desc ); gui->SetStateString( guiImage, image ); } // Tels: Always tell the GUI to refresh the display so the colors change gui->HandleNamedEvent( "UpdateItemColours" ); // Tels: Reset these only after UpdateItemColors gui->SetStateInt( "boughtItem", -1 ); gui->SetStateInt( "soldItem", -1 ); gui->SetStateInt( "dropItem", -1 ); }
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(); }
/* ============ idCVarSystemLocal::SetCVarBool ============ */ void idCVarSystemLocal::SetCVarBool( const char *name, const bool value, int flags ) { SetInternal( name, idStr( value ), flags ); }
/* ======================== idMenuScreen_Shell_SystemOptions::HideScreen ======================== */ void idMenuScreen_Shell_SystemOptions::HideScreen( const mainMenuTransition_t transitionType ) { if( systemData.IsRestartRequired() ) { class idSWFScriptFunction_Restart : public idSWFScriptFunction_RefCounted { public: idSWFScriptFunction_Restart( gameDialogMessages_t _msg, bool _restart ) { msg = _msg; restart = _restart; } idSWFScriptVar Call( idSWFScriptObject* thisObject, const idSWFParmList& parms ) { common->Dialog().ClearDialog( msg ); if( restart ) { // DG: Sys_ReLaunch() doesn't need any options anymore // (the old way would have been unnecessarily painful on POSIX systems) Sys_ReLaunch(); // DG end } return idSWFScriptVar(); } private: gameDialogMessages_t msg; bool restart; }; idStaticList<idSWFScriptFunction*, 4> callbacks; idStaticList<idStrId, 4> optionText; callbacks.Append( new idSWFScriptFunction_Restart( GDM_GAME_RESTART_REQUIRED, false ) ); callbacks.Append( new idSWFScriptFunction_Restart( GDM_GAME_RESTART_REQUIRED, true ) ); optionText.Append( idStrId( "#str_00100113" ) ); // Continue optionText.Append( idStrId( "#str_02487" ) ); // Restart Now common->Dialog().AddDynamicDialog( GDM_GAME_RESTART_REQUIRED, callbacks, optionText, true, idStr() ); } if( systemData.IsDataChanged() ) { systemData.CommitData(); } idMenuScreen::HideScreen( transitionType ); }
/* ============ idCVarSystemLocal::SetCVarFloat ============ */ void idCVarSystemLocal::SetCVarFloat( const char *name, const float value, int flags ) { SetInternal( name, idStr( value ), flags ); }
/* ================ rvGEWorkspace::AlignSelected Align the selected items to the first one using the given align type ================ */ void rvGEWorkspace::AlignSelected ( EItemAlign align ) { static const char* alignNames[]={"Lefts","Centers","Rights","Tops","Middles","Bottoms" }; int i; idStr modName; rvGEModifierGroup* group; assert ( mSelections.Num() > 1 ); modName = "Align " + idStr(alignNames[align]); group = new rvGEModifierGroup ( ); idRectangle rectTo; rectTo = rvGEWindowWrapper::GetWrapper ( mSelections[0] )->GetScreenRect ( ); // Everything gets aligned to the first selection so run // through all other selections and move them. for ( i = 1; i < mSelections.Num(); i ++ ) { float x; float y; idRectangle rectFrom; rectFrom = rvGEWindowWrapper::GetWrapper ( mSelections[i] )->GetScreenRect ( ); switch ( align ) { case ALIGN_LEFTS: x = rectTo[0] - rectFrom[0]; y = 0; break; case ALIGN_RIGHTS: x = (rectTo[0]+rectTo[2]) - (rectFrom[0]+rectFrom[2]); y = 0; break; case ALIGN_CENTERS: x = (rectTo[0]+rectTo[2]/2) - (rectFrom[0]+rectFrom[2]/2); y = 0; break; case ALIGN_TOPS: y = rectTo[1] - rectFrom[1]; x = 0; break; case ALIGN_BOTTOMS: x = 0; y = (rectTo[1]+rectTo[3]) - (rectFrom[1]+rectFrom[3]); break; case ALIGN_MIDDLES: x = 0; y = (rectTo[1]+rectTo[3]/2) - (rectFrom[1]+rectFrom[3]/2); break; default: assert ( false ); break; } group->Append ( new rvGEMoveModifier ( modName, mSelections[i], x, y ) ); } mModifiers.Append ( group ); // Cant merge alignments mModifiers.BlockNextMerge ( ); SetModified ( true ); }
/* ============ idStr::Filter Returns true if the string conforms the given filter. Several metacharacter may be used in the filter. * match any string of zero or more characters ? match any single character [abc...] match any of the enclosed characters; a hyphen can be used to specify a range (e.g. a-z, A-Z, 0-9) ============ */ bool idStr::Filter( const char* filter, const char* name, bool casesensitive ) { idStr buf; int i, found, index; while( *filter ) { if( *filter == '*' ) { filter++; buf.Empty(); for( i = 0; *filter; i++ ) { if( *filter == '*' || *filter == '?' || ( *filter == '[' && *( filter + 1 ) != '[' ) ) { break; } buf += *filter; if( *filter == '[' ) { filter++; } filter++; } if( buf.Length() ) { index = idStr( name ).Find( buf.c_str(), casesensitive ); if( index == -1 ) { return false; } name += index + strlen( buf ); } } else if( *filter == '?' ) { filter++; name++; } else if( *filter == '[' ) { if( *( filter + 1 ) == '[' ) { if( *name != '[' ) { return false; } filter += 2; name++; } else { filter++; found = false; while( *filter && !found ) { if( *filter == ']' && *( filter + 1 ) != ']' ) { break; } if( *( filter + 1 ) == '-' && *( filter + 2 ) && ( *( filter + 2 ) != ']' || *( filter + 3 ) == ']' ) ) { if( casesensitive ) { if( *name >= *filter && *name <= *( filter + 2 ) ) { found = true; } } else { if( ::toupper( *name ) >= ::toupper( *filter ) && ::toupper( *name ) <= ::toupper( *( filter + 2 ) ) ) { found = true; } } filter += 3; } else { if( casesensitive ) { if( *filter == *name ) { found = true; } } else { if( ::toupper( *filter ) == ::toupper( *name ) ) { found = true; } } filter++; } } if( !found ) { return false; } while( *filter ) { if( *filter == ']' && *( filter + 1 ) != ']' ) { break; } filter++; } filter++; name++; } } else { if( casesensitive ) { if( *filter != *name ) { return false; } } else { if( ::toupper( *filter ) != ::toupper( *name ) ) { return false; } } filter++; name++; } } return true; }
/* ================ rvDebuggerServer::CheckBreakpoints Check to see if any breakpoints have been hit. This includes "break next", "step into", and "step over" break points ================ */ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer ) { const statement_t* st; const char* filename; int i; if ( !mConnected ) { return; } // Grab the current statement and the filename that it came from st = &program->GetStatement ( instructionPointer ); filename = program->GetFilename ( st->file ); // Operate on lines, not statements if ( mLastStatementLine == st->linenumber && mLastStatementFile == st->file ) { return; } // Save the last visited line and file so we can prevent // double breaks on lines with more than one statement mLastStatementFile = idStr( st->file ); mLastStatementLine = st->linenumber; // Reset stepping when the last function on the callstack is returned from if ( st->op == OP_RETURN && interpreter->GetCallstackDepth ( ) <= 1 ) { mBreakStepOver = false; mBreakStepInto = false; } // See if we are supposed to break on the next script line if ( mBreakNext ) { Break ( interpreter, program, instructionPointer ); return; } // Only break on the same callstack depth and thread as the break over if ( mBreakStepOver ) { if ( ( interpreter->GetCurrentFunction ( ) == mBreakStepOverFunc1 || interpreter->GetCurrentFunction ( ) == mBreakStepOverFunc2 )&& ( interpreter->GetCallstackDepth ( ) <= mBreakStepOverDepth ) ) { Break ( interpreter, program, instructionPointer ); return; } } // See if we are supposed to break on the next line if ( mBreakStepInto ) { // Break Break ( interpreter, program, instructionPointer ); return; } idStr qpath; OSPathToRelativePath(filename,qpath); qpath.BackSlashesToSlashes ( ); EnterCriticalSection ( &mCriticalSection ); // Check all the breakpoints for ( i = 0; i < mBreakpoints.Num ( ); i ++ ) { rvDebuggerBreakpoint* bp = mBreakpoints[i]; // Skip if not match of the line number if ( st->linenumber != bp->GetLineNumber ( ) ) { continue; } // Skip if no match of the filename if ( idStr::Icmp ( bp->GetFilename(), qpath ) ) { continue; } // Pop out of the critical section so we dont get stuck LeaveCriticalSection ( &mCriticalSection ); // We hit a breakpoint, so break Break ( interpreter, program, instructionPointer ); // Back into the critical section since we are going to have to leave it EnterCriticalSection ( &mCriticalSection ); break; } LeaveCriticalSection ( &mCriticalSection ); }
/* ================ hhWeaponAutoCannon::UpdateGUI ================ */ void hhWeaponAutoCannon::UpdateGUI() { if ( GetRenderEntity()->gui[ 0 ] && state != idStr(WP_HOLSTERED) ) { GetRenderEntity()->gui[ 0 ]->SetStateFloat( "temperature", GetHeatLevel() ); } }
bool InvestigateSpotTask::Perform( Subsystem &subsystem ) { DM_LOG( LC_AI, LT_INFO )LOGSTRING( "InvestigateSpotTask performing.\r" ); idAI *owner = _owner.GetEntity(); assert( owner != NULL ); // grayman #3075 - if we've entered combat mode, we want to // end this task. But first, if we're kneeling, kill the // kneeling animation if( owner->AI_AlertIndex == ECombat ) { idStr torsoString = "Torso_KneelDown"; idStr legsString = "Legs_KneelDown"; bool torsoKneelingAnim = ( torsoString.Cmp( owner->GetAnimState( ANIMCHANNEL_TORSO ) ) == 0 ); bool legsKneelingAnim = ( legsString.Cmp( owner->GetAnimState( ANIMCHANNEL_LEGS ) ) == 0 ); if( torsoKneelingAnim && legsKneelingAnim ) { // Reset anims owner->StopAnim( ANIMCHANNEL_TORSO, 0 ); owner->StopAnim( ANIMCHANNEL_LEGS, 0 ); owner->SetWaitState( "" ); // grayman #3848 } return true; } if( _exitTime > 0 ) { // Return TRUE if the time is over, else FALSE (continue) return ( gameLocal.time > _exitTime ); } // No exit time set, continue with ordinary process if( owner->m_HandlingDoor || owner->m_HandlingElevator ) { // Wait, we're busy with a door or elevator return false; } // grayman #3510 if( owner->m_RelightingLight ) { // Wait, we're busy relighting a light so we have more light to search by return false; } idVec3 ownerOrigin = owner->GetPhysics()->GetOrigin(); // grayman #3492 if( !_moveInitiated ) { idVec3 destPos = _searchSpot; // greebo: For close investigation, don't step up to the very spot, to prevent the AI // from kneeling into bloodspots or corpses idVec3 direction = ownerOrigin - _searchSpot; if( _investigateClosely ) { idVec3 dir = direction; dir.NormalizeFast(); // 20 units before the actual spot destPos += dir * 20; } // grayman #2603 - The fix to #2640 had the AI stopping if he's w/in INVESTIGATE_SPOT_STOP_DIST of the // search spot. This caused sudden jerks if he's closer than that at the start of the // move. To prevent that, check if he's close and--if so--don't start the move. // grayman #3756 - If the stimulus location should be walked to, // as in the case of a suspicious door, don't check whether you're // close enough to just look at the spot. Go there. if( !owner->GetMemory().stimulusLocationItselfShouldBeSearched && // grayman #3756 !_investigateClosely && ( direction.LengthFast() < INVESTIGATE_SPOT_STOP_DIST ) ) { // Wait a bit _exitTime = static_cast<int>( gameLocal.time + INVESTIGATE_SPOT_TIME_REMOTE * ( 1 + gameLocal.random.RandomFloat() ) // grayman #2640 ); // Look at the point to investigate owner->Event_LookAtPosition( _searchSpot, MS2SEC( _exitTime - gameLocal.time + 100 ) ); return false; // grayman #2422 } owner->GetMemory().stimulusLocationItselfShouldBeSearched = false; // grayman #3756 // Let's move // grayman #2422 // Here's the root of the problem. PointReachableAreaNum() // doesn't always look to the side to find the nearest AAS // area at the point's z position. It can move the point to // the AAS area above, or the AAS area below. This makes the AI // run upstairs or downstairs when all we really want him to do // is stay on the same floor. // If the AI is searching and not handling a door or handling // an elevator or resolving a block: If the spot PointReachableAreaNum()/PushPointIntoAreaNum() // wants to move us to is outside the vertical boundaries of the // search volume, consider the point bad. bool pointValid = true; idVec3 goal = destPos; int toAreaNum = owner->PointReachableAreaNum( goal ); if( toAreaNum == 0 ) { pointValid = false; } else { owner->GetAAS()->PushPointIntoAreaNum( toAreaNum, goal ); // if this point is outside this area, it will be moved to one of the area's edges if( owner->IsSearching() && !owner->movementSubsystem->IsResolvingBlock() && ( owner->AI_AlertIndex < ECombat ) ) { // grayman #3070 - point is valid if in combat mode if( !owner->m_searchLimits.ContainsPoint( goal ) ) { pointValid = false; } } } if( pointValid ) { pointValid = owner->MoveToPosition( goal ); } if( !pointValid || ( owner->GetMoveStatus() == MOVE_STATUS_DEST_UNREACHABLE ) ) { // Hiding spot not reachable, terminate task in the next round //_exitTime = gameLocal.time; // grayman #3492 - look at the spot _exitTime = static_cast<int>( gameLocal.time + ( ( float )( INVESTIGATE_SPOT_TIME_REMOTE * ( 1 + gameLocal.random.RandomFloat() ) ) ) / 2.0f // grayman #2640 ); idVec3 p = _searchSpot; p.z += 60; // look up a bit, to simulate searching for the player's head if( !owner->CheckFOV( p ) ) { owner->TurnToward( p ); } owner->Event_LookAtPosition( p, MS2SEC( _exitTime - gameLocal.time + 100 ) ); //gameRenderWorld->DebugArrow(colorCyan, owner->GetEyePosition(), p, 1, MS2SEC(_exitTime - gameLocal.time + 100)); } else { // Run if the point is more than MAX_TRAVEL_DISTANCE_WALKING // greebo: This is taxing and can be replaced by a simpler distance check // TravelDistance takes about ~0.1 msec on my 2.2 GHz system. // grayman #2422 - not the player = walk, player & combat = run, everything else = run // Also, travelDist is inaccurate when an AAS area is large, so compare // it to the actual distance and use the larger of the two. //gameRenderWorld->DebugArrow(colorYellow, owner->GetEyePosition(), _searchSpot, 1, MS2SEC(_exitTime - gameLocal.time + 100)); _moveInitiated = true; float travelDist = owner->TravelDistance( ownerOrigin, _searchSpot ); float actualDist = ( ownerOrigin - _searchSpot ).LengthFast(); if( actualDist > travelDist ) { travelDist = actualDist; } if( travelDist <= MAX_TRAVEL_DISTANCE_WALKING ) { // close enough to walk? owner->AI_RUN = false; } // grayman #3492 //else if ( owner->GetMemory().visualAlert ) // spotted the player by testing his visibility? //{ // owner->AI_RUN = false; // when AI's alert index enters Combat mode, that code will get him running //} else { // searching for some other reason, and we're far away, so run owner->AI_RUN = true; } //owner->AI_RUN = (travelDist > MAX_TRAVEL_DISTANCE_WALKING); // grayman #2422 - old way } return false; } if( owner->GetMoveStatus() == MOVE_STATUS_DEST_UNREACHABLE ) { DM_LOG( LC_AI, LT_INFO )LOGVECTOR( "Hiding spot unreachable.\r", _searchSpot ); return true; } if( owner->GetMoveStatus() == MOVE_STATUS_DONE ) { DM_LOG( LC_AI, LT_INFO )LOGVECTOR( "Hiding spot investigated: \r", _searchSpot ); // grayman #2928 - don't kneel down if you're too far from the original stim float dist = ( ownerOrigin - owner->GetMemory().alertSearchCenter ).LengthFast(); // grayman #3563 - don't kneel down if you're drawing a weapon if( _investigateClosely && ( dist < INVESTIGATE_SPOT_CLOSELY_MAX_DIST ) && ( idStr( owner->WaitState() ) != "draw" ) ) { // Stop previous moves owner->StopMove( MOVE_STATUS_WAITING ); // Check the position of the stim, is it closer to the eyes than to the feet? // If it's lower than the eye position, kneel down and investigate //const idVec3& origin = owner->GetPhysics()->GetOrigin(); idVec3 eyePos = owner->GetEyePosition(); if( ( _searchSpot - ownerOrigin ).LengthSqr() < ( _searchSpot - eyePos ).LengthSqr() ) { // Close to the feet, kneel down and investigate closely owner->SetAnimState( ANIMCHANNEL_TORSO, "Torso_KneelDown", 6 ); owner->SetAnimState( ANIMCHANNEL_LEGS, "Legs_KneelDown", 6 ); owner->SetWaitState( "kneel_down" ); // grayman #3563 } // Wait a bit, setting _exitTime sets the lifetime of this task _exitTime = static_cast<int>( gameLocal.time + INVESTIGATE_SPOT_TIME_CLOSELY * ( 1 + gameLocal.random.RandomFloat() * 0.2f ) ); } else { // Wait a bit, setting _exitTime sets the lifetime of this task _exitTime = static_cast<int>( gameLocal.time + INVESTIGATE_SPOT_TIME_STANDARD * ( 1 + gameLocal.random.RandomFloat() * 0.2f ) ); } } else { // Can we already see the point? Only stop moving when the spot shouldn't be investigated closely // angua: added distance check to avoid running in circles if the point is too close to a wall. // grayman #2640 - keep moving if you're > INVESTIGATE_SPOT_STOP_DIST from a point you can see bool stopping = false; if( !_investigateClosely ) { float distToSpot = ( _searchSpot - ownerOrigin ).LengthFast(); if( owner->CanSeePositionExt( _searchSpot, true, true ) ) { if( distToSpot < INVESTIGATE_SPOT_STOP_DIST ) { stopping = true; } } else if( distToSpot < INVESTIGATE_SPOT_MIN_DIST ) { stopping = true; } } if( stopping ) { DM_LOG( LC_AI, LT_INFO )LOGVECTOR( "Stop, I can see the point now...\r", _searchSpot ); // Stop moving, we can see the point owner->StopMove( MOVE_STATUS_DONE ); // grayman #3492 - Look at a random point that may be anywhere // between the search point and a point 1/2 the AI's height // above his eye level. idVec3 p = _searchSpot; float height = owner->GetPhysics()->GetBounds().GetSize().z; float bottom = p.z; float top = owner->GetEyePosition().z + height / 2.0f; float dist = top - bottom; dist *= gameLocal.random.RandomFloat(); p.z += dist; // Look at the point to investigate owner->Event_LookAtPosition( p, 3.0f ); //owner->Event_LookAtPosition(_searchSpot, 2.0f); // Wait a bit _exitTime = static_cast<int>( gameLocal.time + INVESTIGATE_SPOT_TIME_REMOTE * ( 1 + gameLocal.random.RandomFloat() ) // grayman #2640 ); } } return false; // not finished yet }
int CShop::AddItems( const idDict &mapDict, const idStr &itemKey, ShopItemList &list ) { int diffLevel = gameLocal.m_DifficultyManager.GetDifficultyLevel(); int itemsAdded = 0; // grayman (#2376) // Convert itemKey to lowercase. mapDict methods ignore case, but // StripLeadingOnce() doesn't. This change allows recognition of shop items defined as // "startingItem_*", "startingitem_*", "shopItem_*", and "shopitem_*. idStr itemKeyLower = itemKey; itemKeyLower.ToLower(); bool isShopList = ( itemKeyLower.Find( "shop" ) >= 0 ); // for lockpick checking for( const idKeyValue *kv = mapDict.MatchPrefix( itemKeyLower ); kv != NULL; kv = mapDict.MatchPrefix( itemKeyLower, kv ) ) { // Inspect the matching prefix, check whether the difficulty level applies idStr postfix = kv->GetKey(); postfix.ToLower(); // grayman (#2376) convert postfix to lowercase so StripLeadingOnce() // matches lowercase against lowercase // Cut off the prefix including the following underscore _ postfix.StripLeadingOnce( itemKeyLower + "_" ); int pos = postfix.Find( "_item" ); if( pos == -1 || pos != postfix.Length() - 5 ) { continue; // no suitable "_item" found } // This is the number portion, like "1_2" or merely "2" idStr indexStr = postfix.Mid( 0, pos ); // Check if we have still an underscore in the index string, this implies // that there is a difficulty number included int underScorePos = indexStr.Find( '_' ); // Extract the item index int itemIndex = ( underScorePos != -1 ) ? atoi( indexStr.Mid( 0, underScorePos ) ) : atoi( indexStr ); if( underScorePos != -1 ) { // Check out the second number, this is the difficulty level idStr diffStr = indexStr.Mid( underScorePos + 1, indexStr.Length() - underScorePos ); // Check if the difficulty level matches if( atoi( diffStr ) != diffLevel ) { // Ignore this spawnarg continue; } } idStr itemName = kv->GetValue(); if( itemName.IsEmpty() ) { continue; // Empty names are not considered } // greebo: Assemble the item prefix (e.g. "shopItem_1_") to look up the rest of the spawnargs idStr itemPrefix = itemKey + "_" + idStr( itemIndex ); idStr diffLevelStr = "_" + idStr( diffLevel ); // look for quantity, but let a difficulty-specific setting override the general one int quantity = mapDict.GetInt( itemPrefix + "_qty" ); if( mapDict.FindKey( itemPrefix + diffLevelStr + "_qty" ) != NULL ) { quantity = mapDict.GetInt( itemPrefix + diffLevelStr + "_qty" ); } // put the item in the shop if( quantity > 0 ) { // grayman (#2376) - Special handling for weapon quantities. int index = itemName.Find( "weapon_" ); if( index >= 0 ) { // A shop entity should use atdm:weapon_*, but there's at least one // that uses weapon_*, so convert the latter to the former. idStr weaponName; if( index == 0 ) { weaponName = "atdm:" + itemName; } else { weaponName = itemName; } // Weapon quantities have limits. (Arrows in particular.) int max_ammo = GetMaxAmmo( weaponName ); quantity = ( quantity > max_ammo ) ? max_ammo : quantity; } /* grayman (#2376) - Since a lockpick_set comprises individual picks, putting one on either the shopItems or startingItems list means we don't have to put individual picks on the same list. For now, just register whether a lockpick_set is being added to either list. We'll post-process after the lists are built. */ if( isShopList ) { if( !_pickSetShop && ( itemName.Find( "lockpick_set" ) >= 0 ) ) { _pickSetShop = true; } } else { if( !_pickSetStarting && ( itemName.Find( "lockpick_set" ) >= 0 ) ) { _pickSetStarting = true; } } // look for price int price = mapDict.GetInt( itemPrefix + "_price" ); if( mapDict.FindKey( itemPrefix + diffLevelStr + "_price" ) != NULL ) { price = mapDict.GetInt( itemPrefix + diffLevelStr + "_price" ); } // look for persistency bool persistent = mapDict.GetBool( itemPrefix + "_persistent" ); if( mapDict.FindKey( itemPrefix + diffLevelStr + "_persistent" ) != NULL ) { persistent = mapDict.GetBool( itemPrefix + diffLevelStr + "_persistent" ); } // look for canDrop flag bool canDrop = mapDict.GetBool( itemPrefix + "_canDrop", "1" ); // items can be dropped by default if( mapDict.FindKey( itemPrefix + diffLevelStr + "_canDrop" ) != NULL ) { canDrop = mapDict.GetBool( itemPrefix + diffLevelStr + "_canDrop", "1" ); } CShopItemPtr found = FindShopItemDefByClassName( itemName ); if( found != NULL ) { // grayman - TODO: If there are multiple shops, you can get multiple // entries for the same item. You need to group them into a single item. CShopItemPtr anItem( new CShopItem( *found, quantity, price, persistent ) ); anItem->SetCanDrop( canDrop ); list.Append( anItem ); itemsAdded++; } else { gameLocal.Warning( "Could not add item to shop: %s", itemName.c_str() ); } } } return itemsAdded; }