Jump to content
The Dark Mod Forums

Dragofer

Development Role
  • Posts

    2634
  • Joined

  • Last visited

  • Days Won

    157

Posts posted by Dragofer

  1. 2 hours ago, peter_spy said:

    Anyway, a somewhat related question: was there a specific model you went after for alertness going down? It seems like it's different for some alert levels, e.g. it goes down very fast for "suspicious" and "observant", while it's very slow for "idle" (0-1.5): around 0.01 units/s, which seems like a very long cooldown.

    I didn't design it, but it seems to be governed by these AI spawnargs:

    alert_time1	5
    alert_time2	8
    alert_time3	25
    alert_time4	65

    So it's meant to take 5s to go from alert1 to 0 - still need to factor in other things though, i.e. grace periods and that it takes 2s before alert level is allowed to go down again after an alert. Also need to consider that AIs that have reached a high alert level are not supposed to go below alert level 1 anymore, so they'll patrol with their weapon drawn.

  2. 3 hours ago, Araneidae said:

    @Dragofer, do you still think it's just close range civilians?

    No, just that it's been first reported in this context.

    There was some reworking in TDM 2.05 to how stealth scores get reported for ticket 4002, which restricted which alerts get added to the stealth score. It seems the idea was to wait until the AI returns to alert 0 before deciding how much to add to the score, based on how high the AI alert went during that "alert cycle". The intention was to only count the highest alert stage, not every alert stage passed on the way. Maybe it culls too zealously.

    This is the code block this concerns which I believe is called whenever a mission event occurs, which includes an AI's alert stage changing:

    Spoiler
    void CMissionData::MissionEvent
    	(
    		EComponentType CompType,
    		SObjEntParms *EntDat1,
    		SObjEntParms *EntDat2,
    		bool bBoolArg
    	)
    {
    	DM_LOG(LC_OBJECTIVES,LT_DEBUG)LOGSTRING("Objectives: Mission event called \r");
    	SStat *pStat(NULL);
    	bool bCompState;
    
    	if( !EntDat1 )
    	{
    		// log error
    		goto Quit;
    	}
    
    	// Update AI stats, don't add to stats if playerresponsible is false
    	// Stats for KOs, kills, body found, item found
    	if( ( CompType == COMP_KILL || CompType == COMP_KO
    		|| CompType == COMP_AI_FIND_BODY || CompType == COMP_AI_FIND_ITEM
    		|| CompType == COMP_ALERT ) && bBoolArg )
    	{
    		DM_LOG(LC_OBJECTIVES,LT_DEBUG)LOGSTRING("Objectives: Determined AI event \r");
    		if( CompType == COMP_ALERT )
    		{
    			if( EntDat1->value > MAX_ALERTLEVELS )
    			{
    				// log error
    				goto Quit;
    			}
    			// index in this array is determined by alert value
    			pStat = &m_Stats.AIAlerts[ EntDat1->value ];
    
    			// grayman #4002 - Decide which alert level to record for the stealth score.
    			// If this new alert level is too close to a previous alert level,
    			// then the previous alert needs to be removed.
    
    			// This only applies if the new alert level is higher than EObservant.
    			if ( EntDat1->bIsAI )
    			{
    				int alertLevel = EntDat1->value;
    				if ( alertLevel > ai::EObservant )
    				{
    					idEntity* ent = gameLocal.FindEntity(EntDat1->name.c_str());
    					if ( ent->IsType(idAI::Type) )
    					{
    						// Has this AI registered a previous alert at a lower level,
    						// during this alert cycle? An alert cycle is where an AI rises
    						// from Idle to something higher, then drops back down to idle.
    						idAI *ai = static_cast<idAI*>(ent);
    						int removeThisAlertLevel = ai->ExamineAlerts();
    						if (removeThisAlertLevel > 0)
    						{
    							SStat *pStatPrevious = &m_Stats.AIAlerts[removeThisAlertLevel];
    							// Subtract from all appropriate stats
    							pStatPrevious->Overall--;
    							pStatPrevious->ByTeam[EntDat1->team]--;
    							pStatPrevious->ByType[EntDat1->type]--;
    							pStatPrevious->ByInnocence[EntDat1->innocence]--;
    
    							// Even though pStatPrevious->WhileAirborne might not be the same now
    							// as it was when this previous alert was registered, don't worry about it. It isn't used.
    						}
    					}
    				}
    			}
    		}

    The ExamineAlerts() function, the outcome of which is used by the above code to decide whether to remove an alert from the score:

    Spoiler
    int idAI::ExamineAlerts()
    {
    	int numberOfAlerts = alertQueue.Num();
    	int alertsProcessed = 0;
    	idEntity* entityResponsible = NULL;
    	int nextTime = 0;
    	int nextAlertIndex;
    	int result = 0;
    	bool foundResult = false;
    
    	while (( alertsProcessed < numberOfAlerts ) && !foundResult)
    	{
    		bool newEntity = true;
    
    		for ( int i = 0 ; i < numberOfAlerts ; i++ )
    		{
    			EntityAlert *ea = &alertQueue[i];
    
    			if ( ea->ignore )
    			{
    				continue;
    			}
    
    			if ( newEntity )
    			{
    				// This first entry represents the highest alert level the AI reached.
    
    				entityResponsible = ea->entityResponsible.GetEntity(); // the entity we're currently processing
    				nextTime = ea->timeAlerted;	 // alert time
    				nextAlertIndex = ea->alertIndex; // alert index
    				//ea->processed = true;
    				newEntity = false;
    				alertsProcessed++;
    				continue;
    			}
    
    			idEntity* thisEntityResponsible = ea->entityResponsible.GetEntity();
    
    			if ( thisEntityResponsible != entityResponsible )
    			{
    				continue; // this entry wasn't caused by the entity we're processing
    			}
    
    			ea->ignore = true;
    			alertsProcessed++;
    
    			int thisAlertIndex = ea->alertIndex;
    			int thisTime = ea->timeAlerted;
    
    			// What is the time difference between this entry
    			// and the previous entry (which happens later in time, because the
    			// later entries appear earlier in the queue)?
    
    			int duration = nextTime - thisTime;
    			float alertDuration; // the average amount of time spent at a particular alert level (atime1, atime2, atime3, atime4)
    
    			switch ( thisAlertIndex )
    			{
    			case ai::EObservant:
    				alertDuration = atime1;
    				break;
    			case ai::ESuspicious:
    				alertDuration = atime2;
    				break;
    			case ai::ESearching:
    				alertDuration = atime3;
    				break;
    			case ai::EAgitatedSearching:
    			case ai::ECombat:
    				alertDuration = atime4;
    				break;
    			default:
    				alertDuration = 100000.0f; // should never be here
    				break;
    			}
    
    			alertDuration *= 1000 * 0.5f; // use half the average duration and convert to ms
    
    			if ( alertDuration > 10000.0f ) // suggested by demagogue
    			{
    				alertDuration = 10000.f;
    			}
    
    			// If the latest alert is too close to the previous alert, we should remove
    			// the stats for the previous alert.
    
    			if ( duration < alertDuration )
    			{
    				result = thisAlertIndex;
    				foundResult = true;
    				break;
    			}
    
    			// set up for reading the next entry
    
    			nextTime = thisTime;
    			nextAlertIndex = thisAlertIndex;
    		}
    	}

     

    So from what I read so far it seems older alert stages during an alert cycle get deleted if a new alert stage is reached within a certain timeframe. The timeframe should correspond to half the average amount of time the AI spends at an alert stage as defined in its spawnargs.

    Another possibility is that the variable AIAlerts from MissionStatistics.h isn't updated correctly.

  3. 8 hours ago, Nort said:

    this engine should be held together with tape and glue, and only be fixed after it's fallen apart

    Your problem is you're vastly overstating the significance of those console warnings. The time of skilled devs is a limited resource that's hardly going to be spent going after peanuts.

    And yes, a person who's worked with the project for years is in a 100x better position than you to determine what's a significant bug and what isn't.

    • Like 1
  4. 14 hours ago, Nort said:

    I just want things to work, and not have to clean up unneccessary spill from other's messes.

    This particular line resonates with me, since as it happens I personally put in effort to make sure that the stuff I make doesnt produce console errors (especially my later FMs and anything I develop or vet for inclusion in the core assets). It's a rare day, though, that I want to give my free time in order to clean up other's messes, especially if the problems only manifest in the console and almost no one is disturbed by them. Maybe if I got a nice salary with good perks for it.

    32 minutes ago, Nort said:

    As long as they start with testruns and consulting the console for errors, so that we don't get more issues, they can take as long as they want,

    Well, it seems they do actually do it, so the urgency can be taken out of this discussion?

  5. 14 minutes ago, NeonsStyle said:

    The link is broken, and it's not available in the In Game Downloader. I've downloaded all missions, and

    the downloader is completely empty and your mission is not among them. 

    It's been taken down due to some issues with T-posing AIs and performance. A potential fix is ready, but geegee's away from home for a couple days right now.

    • Like 1
    • Thanks 1
  6. 1 hour ago, Nort said:

    that it's just a matter of incompetence and laziness, why these errors were not fixed a long time ago.

    Professional games come with hundreds of console errors, actually, so it's hardly a result of incompetence but rather a constant byproduct of a large group of people working on a project over several years. You'd need dedicated people just for finding and eliminating them, which is unlikely to happen as most of them (i.e. redefinitions, undefined materials replaced by a skin, missing specular stage) have little if any significance to the user and therefore arent picked up on during testing.

  7. 2 hours ago, Trueblue1878 said:

    Also, are there any missions that take part inside the old underground city? That one was my favourite in Thief.

    Volta 2, Hazard Pay and Requiem fit that description. Written in Stone takes a different approach to its underground ruins. The Painter's Wife has a small detour to a Lost City-like environment, found in a library in the southwest corner of the map.

    I haven't seen many lootlists in TDM - probably because of the availability of the console command tdm_show_loot for showing you all remaining loot for a few seconds.

    • Like 3
  8. 34 minutes ago, Obsttorte said:

    Because that is not what I have written, and you are right that basically the appearence change.

    We might have been reading past each other quite a bit here / peculiarities of the English language (i.e. I also mentioned using the security camera method). Well the main thing is something comes out of it.

    Btw joebarnin said he also tried the AIUse flag + inactive visual stim method but it didn't work for him on a func_fracture, only on a func_static.

  9. 1 hour ago, AluminumHaste said:

    How is that playable? :(

    Its just especially bad in that view because you have the entire train in view (could probably have worked more with func_portals and blocking sight lines). Intel onboard chips have come a long way, relatively speaking: it's now possible to expect 30ish fps in a regular mission.

    Still weird that enabling soft shadows improves my fps, though...

  10. 17 minutes ago, Obsttorte said:

    That's what I wrote, a bit shortened, though.

    Hm, it's not clear to me how you meant that an AIUse flag would get added to the entity when it gets destroyed, since in my understanding "breaking" an entity usually just changes its appearance.

    10 minutes ago, Nort said:

    My other map also has a "ShaderLibrary: definition not found: Default" Dark Radiant console warning on editor load.

    Is this appearing in your maps as well?

    I suppose you have a surface with a missing material, which DarkRadiant names "Default".

  11. 20 minutes ago, datiswous said:

    I think this might be it:

    Thanks, that was exactly what was wrong.

    Hm, still weird that I seem to get the better performance by enabling soft shadows, both on 2.09 and 2.10.

    Starting view of Samuel Wilson 1: Eastbound:

    - Stencil, no soft shadows: 9 fps

    - Stencil, low soft shadows: 14 fps

    - Stencil, medium soft shadows: 13 fps

    - Stencil, high soft shadows: 11 fps

  12. I've just updated my TDM installation to 2.10 with a new darkmod.cfg on my laptop (Intel UHD 630) and found the ingame graphics to be broken: lights seem to be shown as red, yellow or green.

    render1.thumb.jpg.829ee2f71cc55193d5384439bfd55256.jpgrender2.thumb.jpg.b3c8fa43f73e318273ccc88ffe8fa975.jpg

    Looking at the console log for Caduceus of St. Alban (render.txt), I noticed that it complains about the volumetric shader, GL_EXT_depth_bounds_test and GL_ARB_compatibility.

    Any ideas? I quite like the very speedy loading times of 2.10.

    • Like 1
  13. 1 hour ago, Obsttorte said:

    The issue is, that for breakable items the approach was probably intented as that the unbroken entity gets replaced by a broken model that has the AIUSE_BROKEN_ITEM tag set.

    That's how it works for arrows, which get replaced by a different arrow entity upon impact that has the AIUse_SUSPICIOUS flag (exception is fire arrows, which are suspicious already in flight).

    Weapons dropped when an AI is KOed probably work differently, since it looks to me like they're still the same entity. They have AIUse_WEAPON since the beginning - so maybe the code is able to flag a dropped weapon as having belonged to an AI.

    In general, breakable entities specify a different model to show when broken, rather than getting replaced by a new entity. That's also the case with my security camera. It has an AIUse_BROKEN_ITEM flag and an inactive visual stim, and when the security camera is destroyed it starts emitting that visual stim.

    1 hour ago, Obsttorte said:

    Now we don't want to replace the func_fracture entity with something else, as it is capable of representing both the unbroaken and broken state. Therefore I would add a new AIUse tag to allow for that special case. This will take a bit, so if there are any possible drawbacks one can see here, please tell me.

    The problem seems to be, based on joebarnin's report, that AIs never react to a visual stim if it comes from a func_fracture - and that's with the AIUse flag already set at map start.

    If he transfers the stim + flag to the func_static windowframe it works as intended and can be enabled when the func_fracture is destroyed.

    So I don't think it's a problem with the flag, but more with the func_fracture. I remember I explicitly had to add lines to the security camera code to allow it to have Stim/Response, so maybe func_fracture would need that too.

    That said, I think an AIUse flag for entities that can be either in an intact or broken state would be useful, since the AI code could just check whether the entity has become broken rather than needing a trigger to enable the visual stim. Both the func_fracture and the security camera would benefit from that.

  14. 2 hours ago, Obsttorte said:

    @datiswous: You think wrong. Frobbing is applied to all entites, although normally passed onto the bind master. Otherwise a door would behave differently when frobbing the door versus frobbing the handle.

    While making a small light switch with a big housing I actually found frobbing to, by default, only apply to the entity that's in the focus of the frob. If that entity has a frob_master it'll count as if you had frobbed the frob_master instead; frob_peer just makes them highlight together, but has no functional consequences.

    Door handles are a special case handled directly by the code (CFrobDoorHandle), probably so that the mapper doesn't need to setup frob_whatever on all the entities involved.

    2 hours ago, Obsttorte said:

    @wesp5@Dragofer: The best approach might be to simple provide the setup for mappers to use as mission specific. If the feedback is positive and mission authors like it the may be going to use it and "upgrade" their old missions with it. Depending on the amount of agreement this setup gets this could then be done with all left out missions either as than we may agree on it not to be mission-breaking.

    I believe Springheel already did the first step by making the chest bodies of all prefab chests in the core assets unfrobable, so that one can only operate the lid. I've been mapping like this for a while already.

  15. 5 hours ago, Obsttorte said:

    The func_fracture is more a visual thing that was already part of Doom 3. The whole notice something is broken was setup later for TDM and relies on visual stims by the entity in question, which isn't provided by the func_fracture class.

    The idea is to add a visual stim, disabled at map start, to the func_fracture that can be enabled when the glass is destroyed. For some reason the AI is not reacting to the stim if it comes from the func_fracture, or the stim is not being activated due to a mistake in the setup.

  16. 5 hours ago, Obsttorte said:

    Making changes to such setups without missing some special case already present or possible in the future is nearly impossible. That's the issue with non-uniform building styles.

    I think the case of both the chest box and lid being frobable is achievable only in a limited number of ways (froblock + mover_door entities) that mappers almost always use prefabs for. The issue seems to be that mappers sometimes also use such combinations for other applications than chests, i.e. maybe a gate openable via a lockbox somewhere, so in these cases the froblock must always remain frobable and must be recognised and excluded from the script. Wesp5 would know these cases best since he's reported some of them.

    A possible way of making the distinction, even if not 100% sensitive for detecting all desired cases, would be to check whether the froblock entity uses one of the core models for chest bodies (or, for Merry's chest prefabs, contains "merry" in its name).

  17. 19 minutes ago, joebarnin said:

    I still can't figure this out. Anyone out there with ideas? I tried setting AIUSE_BROKEN_ITEM on the window (a func_fracture), but that doesn't work.

    The method I used for destroyed security cameras was:

    • create a visual stim on the security camera and disable it
    • give the security camera the above AIUse spawnarg to identify it as a suspicious broken item
    • when the security camera is destroyed, enable the visual stim

    Func_fractures trigger their targets when they're broken, so you can use that to trigger i.e. a relay or itself with a trigger response to enable the visual stim.

    • Thanks 1
  18. This weird discussion aside, it's perfectly possible to get a full-resolution image via MS Paint simply by saving the image as a jpg (192 kilobytes):

    Untitled.thumb.jpg.3cc4e0596f4225344abad70729a49b0d.jpg

    or png (472 kilobytes):

    Untitled.thumb.png.ca8abb25b9374f5d3337b0a9f4d5a754.png

    and have both fit within the 1000 kilobyte upload limit. I have no idea what you're doing on your end that results in you having to save something as a gif.

  19. On 6/2/2022 at 11:24 AM, Nort said:

    Could you give an example of this doing more harm than good?

    Models with missing textures, missing models showing up as black cubes, missing sounds, maps not loading due to missing scripts or broken entityDefs... the list could go on forever. This is why the TDM team is very conservative with modifying existing assets, especially renaming or relocating them, and only makes such changes after close scrutiny to make sure nothing that relies on these assets (both in core assets and any released FM) will break as a result.

    Obviously just fixing whatever you see in front of you produces fast and easy results, but it's unlikely someone else will do the remaining work to make sure it won't break things elsewhere.

  20. What I do in my missions is to only make the lid frobable to prevent the body from interfering with frobbing the contents. The idea of the script was to apply the same principle to all other missions too, identifying all chests in the map and setting the bodies to nonfrobable. This is hampered by the fact that there are edge cases which use a similar setup to chests and require the "body" entity to be frobable.

×
×
  • Create New...