Jump to content
The Dark Mod Forums

Newbie DarkRadiant Questions


Recommended Posts

2 hours ago, Dragofer said:

I'm not aware of any way to check what key the player is pressing - the only thing I know of is the mouse gesture checking event, which is used to determine which way to swing the sword. The game calls a key press an "impulse", so you might want to use that as a starting point for research.

If the game checks, which way the mouse moves during an attack, it will also have to check that the LMB is pressed at the same time, so it should be possible somehow. Also, the throw distance of the flash bomb etc. is determined by how long the respective button is pushed, so this must also be possible to track somehow. But I don't know if this is somewhere in the source code or if it can also be checked via script.

Link to post
Share on other sites
  • Replies 10.2k
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

So I have this gigantic scorpion, it is made out of pendulums bound together. I had an idea about dragging whole thing through a piled up crates (pretending to be stone blocks in a wall), but it looks

I'm just going to make the lute player an undead immortal skeleton called Ralph who is eternally bound to play his lute in the tavern, the residents are used to him now so they just happily co-exist a

Thanks for the advice about the tent, guys. Finally got around to (mostly) fixing it; shadows were indeed the problem.    

Posted Images

Thanks. I know key presses are called impulses in many engines, that should probably be it; Even if I have to check for a number I can go with that too, granted I know which impulse the USE key is and how to read it. There must be other scripts that check when the use key is being held, I assume a lot of things simply wouldn't work then!

My mod will involve a GUI anyway so just changing the text on that should work. Funny I didn't think of this earlier, it's actually even closer to what I want than a builtin script function randomly printing text somewhere on the screen.

Link to post
Share on other sites

The engine doesn't call key presses only impulses, impulses are just a kind of key presses, in this case a key that you press and it does its work only once, even if you keep the button pressed, in the other end the engine also has the concept of buttons, this is a key that you press and it does it work, over and over again while you keep the button pressed. 

Like always I can only suggest stuff I use on original idtech4 not TDM engine, so with that out the door, to get player key presses you have this:

.getButtons();

this code bellow should also exist in the tdm_util.script

/* Waits for the user to press a button */
void waitForButtonPress() {
	float buttons;

	do {
		buttons = $player1.getButtons();
		sys.wait( 0.01 );
	} while( !buttons );
}

Afaik original idtech 4 has no way to get impulses directly by script only buttons.  Don't know if TDM team changed that. 

I also remember in the doom 3 forum days, talk about a way to do custom player key presses using some console cvar or console command but I don't recall how right now. Will update when I do.  

Edited by HMart
  • Like 1
Link to post
Share on other sites

@HMartExcellent, thanks for sharing that - getButtons() is very well alive in TDM (I always assumed it had to with button entities ingame). And looking at darkmod_keybinds.cfg, we have (probably)all the names of the buttons/impulses that TDM uses:

unbindall
bind "ENTER" "_impulse51"
bind "ESCAPE" "togglemenu"
bind "SPACE" "_moveup"
bind "-" "_impulse50"
bind "0" "_impulse10"
bind "1" "_impulse1"
bind "2" "_impulse2"
bind "3" "_impulse3"
bind "4" "_impulse4"
bind "5" "_impulse5"
bind "6" "_impulse6"
bind "7" "_impulse7"
bind "8" "_impulse8"
bind "9" "_impulse9"
bind "=" "_impulse49"
bind "P" "map test"
bind "[" "_impulse48"
bind "\" "_mlook"
bind "]" "_impulse47"
bind "^" "_impulse0"
bind "a" "_moveleft"
bind "c" "_impulse24"
bind "d" "_moveright"
bind "e" "_impulse46"
bind "f" "_impulse44"
bind "g" "inventory_use '#str_02396'"
bind "i" "inventory_cycle_group '#str_02391'"
bind "k" "inventory_cycle_group '#str_02392'"
bind "l" "inventory_use '#str_02395'"
bind "m" "inventory_cycle_maps"
bind "o" "_impulse19"
bind "p" "map test"
bind "q" "_impulse45"
bind "r" "_impulse52"
bind "s" "_back"
bind "u" "_impulse51"
bind "v" "inventory_hotkey '#str_02397'"
bind "w" "_forward"
bind "x" "_impulse23"
bind "y" "clientMessageMode 1"
bind "z" "_zoom"
bind "BACKSPACE" "inventory_hotkey"
bind "PAUSE" "pause"
bind "UPARROW" "_forward"
bind "DOWNARROW" "_back"
bind "LEFTARROW" "_left"
bind "RIGHTARROW" "_right"
bind "ALT" "_strafe"
bind "CTRL" "_button5"
bind "SHIFT" "_speed"
bind "DEL" "_lookdown"
bind "PGDN" "_lookup"
bind "END" "_impulse18"
bind "F3" "_impulse17"
bind "F4" "savegame quick"
bind "F5" "loadgame"
bind "F6" "_impulse20"
bind "F7" "_impulse22"
bind "F9" "loadgame quick"
bind "F12" "screenshot"
bind "MOUSE1" "_attack"
bind "MOUSE2" "_impulse41"
bind "MOUSE3" "_zoom"
bind "MWHEELDOWN" "_impulse14"
bind "MWHEELUP" "_impulse15"

Impulses don't seem to be in the TDM Script Reference, but "buttons" should do nicely well enough.

Link to post
Share on other sites

Yes: $player1.getButtons() is the part I needed. I already have a per-frame loop function to use it from. Use key appears to be _impulse51 judging by that list?

Only remaining question here is how I filter a given key from it, extract whether a given button is pressed from that getButtons(). I know in other codes you typically use something like |= or ~&= to see if contains a button's bit.

Link to post
Share on other sites

Using the Conversation Editor... as the last element of a Conversation, I'm trying to use RunScript to call a global script function. I've seen no evidence that the function is every called. I've tried configuring the call -

- with and without an Actor specified

- with and without an entity parameter in the called function

- with and without the Wait For Completion flag set

Well, maybe not as methodically as the above suggests. But anyway, is there some way to make this work? I want to use scripting to manage a network of Conversations.

Link to post
Share on other sites

IIRC I've called a lot of scripts in the conversations of The Painter's Wife. Anyway if worst comes to pass you can probably just make one of the actors activate a callscriptfunction entity.

Link to post
Share on other sites

Good workaround idea, Conversation's ActivateTarget on a callscriptfunction.

BTW, I was earlier able to use an ActivateTarget on a trigger relay to in turn call a target_startconversation, so creating an overall conversational loop... but I need more complex flow control, and that's easiest to do in script.

Link to post
Share on other sites

Had some free time and while trying to get the hang of dark radiant tools, I found very furstrating the "leak" issue. As the map gets more complex I got lost in the structure making it very time consuming to find the leak. I tested a work around by enclosing the whole map or at least the specific area that leaks with a "walled" brush. I am not sure if it is aceptable in terms of performance later on but upon testing the map I don't see any performance issues neither I can locate any leaks opticaly at least. Is it ok to use this method?

Also I found the subtract tool very usefull (like dromed) but upon watching older tutorials on its function I heard that it is better not to be used because it can lead to problems later on. Does that apply even now after all the updated versions of dark radiant?

Edited by kin
Link to post
Share on other sites

Flooding the map (what can cause leaks) is not done due to performance, but for pathfinding. So it may not affect performance all too much (unless you have lots of AI walking around) but may cause issues with pathfinding. You can use the pointfile to track down the leak. Once you get used to it it is fairly simple. If you still encounter issues and/or often stumble into having leaks you may overthink your mapping workflow, too.

 

The Substract Tool can cause brushes to be split up into lots of smaller brushes and does not grant you any control over how the splitting is done, which can lead to malformed brushes thats surfaces consisting out of long thin tris, of which the first one can be bad for performance and the latter can cause you graphic issues. The tool is perfectly fine for cutting axis-aligned cuboid holes into an axis-aligned cuboid brush, for example when making doors or windows, but if used to create details the result is not good and the tool should notbe used for that purpose. Although I personally think that never was the intention behind it. So or so details shouldn't be worldspawn either way.

  • Like 1

FM's: Builder Roads, Old Habits, Old Habits Rebuild

Mapping and Scripting: Apples and Peaches

Sculptris Models and Tutorials: Obsttortes Models

My wiki articles: Obstipedia

Texture Blending in DR: DR ASE Blend Exporter

Link to post
Share on other sites

@kin, my experience likewise is that leak finding is often time-consuming and frustrating. Just budget time for it and persevere. You will get better at it, but it's never fun. There will be ample opportunities for practice: once you've gotten the external leaking under control, then you have to move on to internal leaks associated with visportals and (optionally) sound-related info_locations. Diagnosis of these leaks also make use of pointfiles. Sometimes, the leak cause is immediately obvious. For the tough case, you have to experiment, e.g., by putting in temporary walls (or converting visportals temporarily to solid walls) or big blocking cubes to isolate and investigate hypotheses.

Here's some things I've learned:

- If you're putting in a brush that you intend to block leaks, make its faces aligned with the world axes if possible.

- But if you want it to be at an angle, don't hand-rotate it. Instead, use DR's Modify/Rotate and Scale... [not Modify/Rotate] to rotate a precise angular amount. This makes it much easier if you want to abut another angled wall against it.

- If you've already got two hand-rotated walls abutting but leaking, enlarge either or both to overlap each other at the leak area, then use the clipper tool to trim them both to share the same face. Or throw the walls away and redo them with precise angles.

- If you've got brushes with faces that don't align with any world axes, then fine-adjusting those faces, or trimming them with the clipper tool, is just about impossible. In those cases, you might have to coarsely overlap brushes to stop leaks. Be aware that this solution can cause walls to not render ("disappear") in the game.

Link to post
Share on other sites

@Dragofer, the good news is that this works (abstract syntax here):
 

conversation1.ActivateTarget(target_callscriptfunction with "call done_1") -->

void done_1() {sys.wait(0.1); sys.trigger($target_startconversation_2 with "conversation conversation2")  -->

start of conversation 2

The wait(0.1) is required, or else the audio in conversation 2 doesn't play.

OK, the bad news...

1) When a new conversation is triggered, the AI idle animations glitch/jump. Haven't found a way to prevent this. (I'm only using the AIs' idle animations, not specifying anims in the conversations themselves).

2) With a longer ogg file in the conversation (e.g., singing for 20 seconds), lip sync gets a significant offset, e.g., the lips move 1 second later than the sound). A hypothesis is that precaching/preloading the sound would fix this. Anyone have a recommendation for the best way to do this with a conversation sound shader (which in some cases may have multiple ogg files)?

Link to post
Share on other sites

1) I'd guess youre calling conv 2 too soon after conv 1. Does it still happen if you wait i.e. 5s or call conv 2 first and from a separate script?

2) Putting the soundshader in a "snd_" spawnarg automatically precaches it on that entity.

Link to post
Share on other sites

1) Later today I'll try some experiments along the lines you suggest. But even if that's the case, I can't put in a 5 second delay; conv1 and 2 are all part of an overall conversation flow that would be too halting with delays like that. The glitching would be the lessor of 2 evils.

2) Let me see if I understand what you're saying. In my atdm_conversation_info_1, that holds all the conv, I should have snd_1, snd_2, etc. with the names of the sound shaders? Or should they be on the AIs that speak them?

Link to post
Share on other sites

@Kin, the subtract tool is bad because it very often leads to shattering a brush into countless triangle shards, which is almost always going to be bad news no matter how the engine is optimized. It definitely (okay, probably) shouldn't be used if the surface or wall is separating leafs, i.e., standing between two visportal-separated areas, and it's best used, if at all, basically in contained places where you'd feel okay putting a 10,000 triangle model or the like.

Or you just do it in a way that doesn't make so many small triangles; but if you could do that, then you can probably do that in other ways too. To wit: the thing is, most of the things you could do with the subtract tool you could also do with the cut tool, and it doesn't take even that much longer to use the cut tool for much less potential for headaches later on.

But they kept the subtract tool in because sometimes it really is handy, like if you wanted to make a star-shaped hole in a pillar, there's not much better way to do it. That kind of thing.

-------

The impulse discussion reminded me of a Halloween themed FM I was working on once where the player started off inside a closed coffin, along with a lantern and pesky rat that's scurrying around inside there with you; and the first part of it was finding a way to escape. Anyway, to make it believable, I had the player crouched in a false bottom with the head exactly placed at the head of a headless player model, so you're looking across at your body. So I had the game start with a crouch impulse. It kind of worked, but IIRC something was always a little off so I never did finish it off. I still think it was a cool idea though. Maybe I'll get back to it someday.

What do you see when you turn out the light? I can't tell you but I know that it's mine.

Link to post
Share on other sites
On 12/18/2020 at 10:07 PM, MirceaKitsune said:

Yes: $player1.getButtons() is the part I needed. I already have a per-frame loop function to use it from. Use key appears to be _impulse51 judging by that list?

Only remaining question here is how I filter a given key from it, extract whether a given button is pressed from that getButtons(). I know in other codes you typically use something like |= or ~&= to see if contains a button's bit.

There's a link to the doom3 wiki on my reply above that has a example on how to use that function with Doomscript, with the Doom 3 game button functionality in mind but I think it can be converted to TDM very easily if you know how TDM buttons are set up. 

Btw again, unless TDM team changed things, you can't get the values of impulses from .getButtons(), it only returns the value of usercmd.buttons.  

Meaning that any key binded to a impulse is unfortunately off limits in DoomScript, in the case of original Doom 3 engine you only have access to seven buttons with that script function and apparently based on the link below because of a engine bug the button seven, didn't even worked well, don't know if still true in TDM.

http://web.archive.org/web/20050404051342/http://www.planetdoom.com/d3cc/tut02.html

Not really useful for scripting but if you are curious, you can look at TDM c++ source code, I assume inside UsercmdGen.h to know what value each impulse or buttons is set too.

Edited by HMart
Link to post
Share on other sites
7 minutes ago, HMart said:

There's a link to the doom3 wiki on my reply above that has a example on how to use that function with Doomscript, with the Doom 3 game button functionality in mind but I think it can be converted to TDM very easily if you know how TDM buttons are set up. 

Btw again, unless TDM team changed things, you can't get the values of impulses from .getButtons(), it only returns the value of usercmd.buttons.  

Meaning that any key binded to a impulse is unfortunately off limits in DoomScript, in the case of original Doom 3 engine you only have access to seven buttons with that script function and apparently based on the link below because of a engine bug the seven button didn't even worked well, don't know if still true in TDM.

http://web.archive.org/web/20050404051342/http://www.planetdoom.com/d3cc/tut02.html

Not really useful for scripting but if you are curious, you can look at TDM c++ source code, I assume inside UsercmdGen.h to know what value each impulse or buttons is set too.

So there isn't a reliable way to check if the USE key is being pressed? In its case though what userbutton would I try to go for... like which of the bits is the use key? Maybe it works, but sadly it feels a bit unreliable from what you're saying.

Link to post
Share on other sites

1) 5 second delays did not stop glitches.

2) Adding the snd_... to the AIs did not solve the out-of-sync problems. (Subjectively, it is possible it made it somewhat better at the margins.) This result makes it more likely that the singing will have to be broken up into short phrases. Not a good outcome.

Link to post
Share on other sites
1 hour ago, MirceaKitsune said:

So there isn't a reliable way to check if the USE key is being pressed? In its case though what userbutton would I try to go for... like which of the bits is the use key? Maybe it works, but sadly it feels a bit unreliable from what you're saying.

By USE key you mean the frob key? If so, why are you trying to know directly the state of the frob key? There's no other way to know if the player is frobbing something?  What are you trying to do? 

But so you know, looking at TDM source, currently yes, you cannot get the frob key value using .getbuttons(), because is managed by a impulse, _impulse41. 

case IMPULSE_41:		// TDM Use/Frob
		{
			// grayman #3746 - If a readable gui is currently displayed
			// we need to ask for it to be closed.
			if ( m_immobilization.GetInt("readable") )
			{
				// Pass the "inventoryDropItem" event to the GUIs
				m_overlays.broadcastNamedEvent("inventoryDropItem");
			}
			else
			{
				// Register the button for tracking
				m_ButtonStateTracker.StartTracking(impulse);
				// Perform the frob
				PerformFrob();
			}
		}
		break;

 But TDM most have other ways in script to know if you are frobbing (using) or not a object is basic functionality?!

If you really need to get the state of a key, then afaik this are the buttons that you can realistically check. You just need to bind a key to any of them. For example, bind "e" "_attack",  then when you press key "e" it will set usercmd.buttons to UB_ATTACK and that can be retrieved by .getButtons() script function.  

	{ "_attack",		UB_ATTACK },
	{ "_speed",			UB_SPEED },
	{ "_zoom",			UB_ZOOM },
	{ "_showScores",	UB_SHOWSCORES },
	{ "_mlook",			UB_MLOOK },

	{ "_button0",		UB_BUTTON0 },
	{ "_button1",		UB_BUTTON1 },
	{ "_button2",		UB_BUTTON2 },
	{ "_button3",		UB_BUTTON3 },
	{ "_button4",		UB_BUTTON4 },
	{ "_button5",		UB_BUTTON5 },
	{ "_button6",		UB_BUTTON6 },
	{ "_button7",		UB_BUTTON7 },

 

Edited by HMart
Link to post
Share on other sites

MirceaKitsune was looking for the "Use" key, which is how keys can be used on doors. And yes, that'd be _impulse51. Frobbing is something else - there are many ways to call a script when a specific entity is frobbed, but not to my knowledge whether the player is frobbing any entity, as you're busy working out.

Link to post
Share on other sites
4 minutes ago, Dragofer said:

MirceaKitsune was looking for the "Use" key, which is how keys can be used on doors. And yes, that'd be _impulse51. Frobbing is something else - there are many ways to call a script when a specific entity is frobbed, but not to my knowledge whether the player is frobbing any entity, as you're busy working out.

If is a impulse then is like the frob unfortunately. 

About if the player is frobbing a entity, looking at the code there's a script event defined for it.

// ishtvan: Let scripts get the currently frobbed entity, and set "frob only used by" mode
const idEventDef EV_Player_GetFrobbed("getFrobbed", EventArgs(), 'e', 
		"Returns the currently frobhilighted entity. This includes entities the player has in his hands. Sets \"frob only used by\" mode");

void idPlayer::Event_GetFrobbed() const
{
	idThread::ReturnEntity( m_FrobEntity.GetEntity() );
}

doesn't "&player1.getFrobbed()" work?

Link to post
Share on other sites
1 hour ago, MirceaKitsune said:

So using the .getButtons() example, how do I get _impulse51? That seems to be using a bit: 1, 2, 4, 8, 16, etc. Is it known which bit that impulse is?

I don't know how to say this any other way. That function gets the value of usercmd.buttons while impulses are normally handled by usercmd.impulse, they are two different variables, so you should never get impulses using .getButtons() (unless TDM team changed something that I'm failing to see in the source).

About that particular impulse value, looking at TDM source code and counting by hand, _impulse51 == 76, so if you press the key binded to _impulse51 and .getButtons() returns 76 that means I'm wrong, you can access impulses in TDM, try it.

Edited by HMart
Link to post
Share on other sites
29 minutes ago, HMart said:

I don't know how to say this any other way. That function gets the value of usercmd.buttons while impulses are normally handled by usercmd.impulse, they are two different variables, so you should never get impulses using .getButtons() (unless TDM team changed something that I'm failing to see in the source).

About that particular impulse value, looking at TDM source code and counting by hand, _impulse51 == 76, so if you press the key binded to _impulse51 and .getButtons() returns 76 that means I'm wrong, you can access impulses in TDM, try it.

Yeah this is a bit confusing. And indeed I should be able to simply print what .getButtons() says while holding down different buttons, that should give me the necessary result. 76 seems wrong though as it's not a power of two, IIRC that's how bits work.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...