Jump to content
The Dark Mod Forums

Newbie DarkRadiant Questions


Recommended Posts

  

47 minutes ago, MirceaKitsune said:

Managed to fix all of the above issues! Except for two which are the last things I need to finish the script: Detecting if the AI is dead or alert. Please let me know how to properly check the AI_DEAD and AI_AlertLevel flags.

The AI can be made to properly speak a line using ai.bark("snd_greeting_generic"). Only limitation is that the sound needs to be defined in the vocal set, you can't use custom sounds... a small price to pay for salvation :)

I remember those states in the sourcecode but wouldn't be able to remember how to get them from a script in-game.

I just wanted to post to make a side rant (sorry)... It's an old issue that all or most actions like frobbing pass the player object and not the frobbed object, when obviously the key piece of info is the thing being frobbed not that the player is frobbing it (since unless/until we get multiplayer, it's always going to be the player1). Tels actually fixed it, but I think because it would break one puzzle in one FM, we didn't go with it... So now we have to make a new script for literally every object we could frob. Imagine 100 scripts when you could just have one with one conditional up front checking the passed object. And then around the same time a lot of FMs needed to be re-released anyway because of 2.0. Now I just wish we had Tel's fix.

 

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
  • 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

@demagogue
Ah right, I just assumed global scripts would at least pass the entity they were activated from, rather than just player1 all the time. That's completely useless and would mean having to write one unique script per entity.

Fortunately scriptobjects are able to solve that, since you can make all entities use the same piece of script but the variables can all be unique to the entities. For instance they allow you to use self, instead of having to refer to specific entities by name. Only problem is each entity can have only one scriptobject, so it requires creative thinking if the entity already has one i.e. a lamp with the light_holder scriptobject.

@MirceaKitsune
AI flags (all-capitalised) are a special case and their syntax keeps eluding me. I know @joebarnin
has worked with them, so maybe he can point out an example line.

If it's something that starts with get..., it's a function so you always need to append brackets at the end, even if you aren't calling the function with any parameters. So like $ai1.getAlertLevel();

Also, regarding $ai1, it was intended that you'd change the "ai1" name to whatever your AI is called. The $ causes the script to look for an entity ingame with that name.

Link to post
Share on other sites
4 hours ago, demagogue said:

  I just wanted to post to make a side rant (sorry)... It's an old issue that all or most actions like frobbing pass the player object and not the frobbed object, when obviously the key piece of info is the thing being frobbed not that the player is frobbing it (since unless/until we get multiplayer, it's always going to be the player1).

The object being frobbed can be read out with $player1.getFrobbed(). If you use this instead of an entity name, this can also be used in more general scripts.

Regarding the alerted/dead states, you could try to not use these flags directly, but use the varaibles that cause the states to change. Dragofer already mentioned the getAltertLevel function for alerted AI. In order to check, if an AI is dead, you could try the getHealth function. For a dead AI Health should be 0, so this could work.

Link to post
Share on other sites
12 minutes ago, Destined said:

The object being frobbed can be read out with $player1.getFrobbed(). If you use this instead of an entity name, this can also be used in more general scripts.

That would be do the trick if that's how it works. All the objects call one script, then you get the frobbed object from that & put a conditional up front that routes the script based on what object was frobbed that called the script.

I mean if it gets the very object the player frobbed that called that script, as opposed to the last object the player frobbed or the object they happen to be frobbing right at that moment, which may well be a different object. That's what I'd want to double check.

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
2 hours ago, Destined said:

The object being frobbed can be read out with $player1.getFrobbed(). If you use this instead of an entity name, this can also be used in more general scripts.

Regarding the alerted/dead states, you could try to not use these flags directly, but use the varaibles that cause the states to change. Dragofer already mentioned the getAltertLevel function for alerted AI. In order to check, if an AI is dead, you could try the getHealth function. For a dead AI Health should be 0, so this could work.

Ah, getFrobbed looks useful. It looks like it checks what entity is currently frob-highlighted, so if this gets called the same frame that the entity is frobbed it should have the desired effect.

Checking health would be fine for substituting AI_DEAD, but he'd also need something to check if the AI is knocked out. Well, maybe it doesn't matter because I doubt bark functions will do anything if called on a ragdoll.

Link to post
Share on other sites

I was able to refer to the frobbed entity by giving my function an entity parameter: I think TDM knows how to send it by default or something. So using this definition I'm able to refer to the frobbed AI as "self":

void ai_frob (entity self)

I already looked on the scripting reference wiki page and could not find a builtin way to check if the AI is dead or alert. The closest function for alerts is getAlertLevelOfOtherAI() but as its name implies it refers to another AI. Closest thing I could try with the available functions is this, but it doesn't work unfortunately (AI still talks while alert):

if(self.getAlertActor() == $null_entity)

And death / knockout does need to be checked for: I tried killing then frobbing the AI, and the dead body will still talk with lipsyncing when being picked up... had a nice laugh at that last night :D

  • Like 1
Link to post
Share on other sites
15 minutes ago, MirceaKitsune said:

I was able to refer to the frobbed entity by giving my function an entity parameter: I think TDM knows how to send it by default or something. So using this definition I'm able to refer to the frobbed AI as "self":


void ai_frob (entity self)

 

Yes that's what I suggested yesterday on the Discord, I was surprised when it didn't seem to be working earlier, i.e. always passing player1.

For alert state, I've done some scripting based on that in invernesse.script, part of Down by the Riverside. It's also possible that I've used AI_ booleans in The Painter's Wife. Can't access that atm.

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

For checking if an AI is dead, I had to define a variable and cast it to the AI name. Like this:


ai guard = $atdm_ai_guard_elite_1;
if (guard.AI_DEAD) ...

I suspect AI_AlertLevel is the same. E.g.


if (guard.AI_AlertLevel > 10) ...

 

Using self in this case, I still get the crash on startup. I really wonder what might be causing it :(

void ai_frob(entity self)
{
	if(!self.AI_DEAD)
	{
		...
	}
}
Sys_Error: Error during initialization. Error: file fms/testing/script/ai_frob.script, line 4: Unknown value "AI_DEAD"

 

Link to post
Share on other sites

Joebarnin implies that you need to define self as an "ai" before you can use AI_DEAD on it. Don't think you can use the name "self" again, so name it i.e. "guard" instead. So

ai guard = self;

if (!guard.AI_DEAD)

...

 

 

Or try void ai_frob(ai self) instead of void ai_frob(entity self)

  • Like 1
Link to post
Share on other sites

I think DragoFer is right, self is a doomScript special keyword, is a pointer to the current entity/object/class (is like "this" in c++ ) and shouldn't be used as a variable name. I find it really bad how the script compiler don't detect, such basic error and just gives a cryptic error message, is for this reason and others that I decided to ditch doom script and code everything in c++ instead. 

edit: Because i code in c++ for so long now, sometimes I don't recall some of the script stuff.  

So i ask, is "ai" a valid object type, derived from entity? Meaning can you assign a entity (self) to a ai object? Unless "self" points to a ai object that is... 

In original idtech 4 I would do something like this:  (not tested)

entity guard = $atdm_ai_guard_elite_1;

if(guard) {

    float healthAmount = guard.getHealth( );

    if(healthAmount <= 0) { /*do something*/ }

}

Edited by HMart
Link to post
Share on other sites

Ok went to see some ai scripts and it seems "ai" is indeed a valid object type, in Doom 3 at lest it serves the purpose of a enum, in this case a object full of booleans. 

DragoFer suggestion is the better one in this case. And my code suggestion is also to the case where the ai is dead not alive.

Link to post
Share on other sites

Yes, you can specify subcategories of entities such as ai, light or tdm_elevator, instead of the more generic "entity". That opens up some additional options, such as in this case the AI_ booleans for an entity defined as an "ai".

  • Like 1
Link to post
Share on other sites

Confirming it worked: Replacing "entity self" with "ai self" is what was needed to fix that last issue.

I have everything I need now. The script is working perfectly and I'm loving the results I get! Thanks once more for the help :) I'm doing the finishing touches and should be able to post it tomorrow.

  • Like 2
Link to post
Share on other sites

There's another little something I wanted to work on in terms of scripting. I wanna keep exactly what I'm doing a surprise... maybe I'll decide to release this one as a Christmas gift or something :) So instead I'm going to ask about exactly the stuff I need to do with my script... this time a script that affects the player. Here's a few different things I need to do for starters:

  1. How do I define a custom variable on an entity, in this case the player? I know I can't just write $player1.mycounter = 10 as the script would complain that "mycounter" is not defined: Is a separate function needed to declare it first?
  2. When the player is damaged by anything in the environment, I need to know the amount of damage that was dealt. Just as importantly I must know either the direction the damage came from relative to the player (as a vector), or even better the proximity of the damage to a given bone (eg: how close it was to "hand_r").
  3. Does a custom script allow me to access and modify generic player parameters? This includes things like: The walk / run speed, the jump speed (how high the player jumps), whether the player is allowed to run or jump at all, and I'm curious if it's possible to force the player into always crouching. Additionally I'd like to modify the accuracy of arrows, how long it takes to draw them, and for how long the player can hold an arrow drawn before he tires out. Can I also change how difficult it is for the player to carry an item in the world, like how boxes drag behind more slowly because they're heavier?
  4. How can the script call a GUI with a number parameter? I've seen the $player1.callGui(mygui, callname) command which does what I want but I can't parse variables with it: I'd like something just like that but which allows me to pass a float variable for the GUI to use. Or maybe the GUI definition lets me read a variable from the player instead?
  5. Another GUI related question: When using this command to modify the GUI from the script, is it possible to tell it that I want a change to fade? Like if I change the color or alpha of a GUI element: Instead of it instantly snapping to the new color / alpha, can I tell the engine I want a smooth transition during say 0.5 seconds?
  6. Yet another final GUI question: I'm doing this for a HUD, so how do I tell the whole thing to follow the alpha of the HUD as configured in the settings menu? Ideally even resize with it as IIRC that's also an option in the HUD menu.
Edited by MirceaKitsune
Link to post
Share on other sites

1. Variables you define yourself aren't specific to entities if you're using map scripts. They're only specific to an entity if you're writing a scriptobject, in the sense that variables defined in that entity's scriptobject won't be visible to map scripts or other entities' scriptobjects.

So just do

float mycounter = 10;

 

2. I'm not aware of a method to call a script whenever the player's health is lowered. I know there is a system for checking which bone was hit when damage is applied to an AI, but I'm not aware of how it can be applied to the player, or whether the player even has bones (the optional player model probably has bones, but is it in any way used for hit detection?). The best I could offer would be a permanently looping script that checks the player's health every 0.x seconds. Maybe you can find out how the red blood effect on the screen gets triggered, i.e. via a GUI script or player scriptobject. There is the signal system which contains an onDamage signal, but I think that system applies only to func_movers.

 

3. VanishedOne has made a speed potion, worth looking into how that was scripted. Kingsal has increased bow draw speed, at least in Volta 3, but I think that was an entity tweak. Maybe check the player's entity defs and see if you can change some of the parameters in there, possibly the same way VanishedOne modified running speed. There is a force multiplier cvar for dragging moveable bodies, maybe you can find a way to change that from a script.

 

4. kcghost has scripted a GUI element (inventory item) which uses a script to update its text dynamically (stealth score): https://forums.thedarkmod.com/index.php?/topic/20245-view-stealth-score-during-gameplay/&do=findComment&comment=443437

 

5. See the GUI message scriptobjects to see how to fade a GUI overlay's transparency.

 

6. I have no idea. Maybe look at one of the existing HUD elements that does adhere to opacity settings, and dissect how it was made. It helps to unpack your TDM installation to more easily get at the files, without having GUI defs spread out over multiple .pk4s.

Link to post
Share on other sites

I see... definitely gets more complicated, thanks. It's worth noting that in this case what I'm trying to do isn't a map script but an addon, intended to work in every FM and which people can install by placing the pk4 in their TDM directory. Of course it's limited to the "hooks" allowed by map script functions as I don't plan to modify default scripts (that would be a nightmare to maintain even if I knew how to do it).

Yes I was thinking of checking health changes in a loop, which from other examples I'm seeing is as simple as using while(1). The problem is that for what I need I also must get the direction the damage came from; Bones are indeed overboard as the player model is only rendered for limited visual purposes, so I'd be better off with a vector of the form <left-right, front-back, top-bottom> (eg: <-0.75, 0.23, 0.14>) relative to the player's orientation... no idea how to get that.

I'm assuming many stats are stored as variables for the player objects, but I'm not sure if enough of them to make what I want possible. Which well I guess I can say includes a skill system among other things, where certain capabilities would be possible to upgrade (player walk speed, player jump speed, how silent the player is while walking, additional decreases in the light gem so the player stays more hidden, faster and better bow firing, etc). It would really help if someone could point out every such variables that exist and which I can edit... I'll look at existing scripts that I can find too but not many FM's with such functionality come to mind.

Edited by MirceaKitsune
Link to post
Share on other sites

Most of the above issues have been answered. Seems I can discover a lot by looking at the script reference wiki page mixed with unpacking the default scripts directory and using grep to look through the code. Only a simplistic implementation is possible but I can put part of my idea in practice at least.

For movement $player1.setHinderance and $player1.setTurnHinderance are what you need... could have really used one for jumping too but for now this will do. $player1.disableWeapon and $player1.enableWeapon can be used to block the weapon.

Only concrete question that remains unanswered is how to make my HUD GUI follow the HUD settings in the main menu. Size too if possible but at least the alpha! Let me know if anyone has the parameters required.

Link to post
Share on other sites

What do you mean by HUD settings? The looks? The ways I know "to talk" to a gui, is using onNamedEvent's, global "gui::varname" variables particular to each gui, using the "runscript" command inside the gui

examples:

// what this one does is run ANY script func name, from a script attached to the entity this gui belongs, gui::gui_parm6 is a placeholder.
runScript "gui::gui_parm6";

// this one only runs the script name you give it and only that, in this case a particular script func from a map script
runScript "map_name::functionName"; 

or the "set" command also inside the gui

examples:

set "cmd" "resetCvars";
set "cmd" "play guisounds_menuclickup";
set "cmd" "runScript map_cpuboss::bridge_rotate_east ; play guisounds_action"; // you can put more than one command seperated by ;

and of course directly through script and or c++.

For script there's: 

Quote

$my_entity.setGuiParm("key", "value");  // the key is the "gui::varname" like the "gui::gui_parm6" above. the gui:: is omited tho.

Disclaimer: This is basic Doom 3 idtech 4 commands, TDM engine team, may have changed, removed or implemented better functionality in the mean time.

Edited by HMart
Link to post
Share on other sites

I'm referring to the settings in this menu:

river_2020-12-13_21_49_11.thumb.jpg.50283d85516415bf5c49cf27e65754e4.jpg

I want to attach custom components to the lightgem for instance, thus I'd like my GUI element to follow its size setting and especially the HUD opacity. The settings themselves are just cvars so I'd only need to know their names... followed by how a GUI definition can translate a float cvar into a rectangle component (I'll look for the answer among existing GUI's).

Edited by MirceaKitsune
Link to post
Share on other sites

Running into a few more issues. One is how I'm trying to spawn a speaker (attached to the player) and have it loop a sound... $player1.startSound() doesn't handle looping nor does it allow me to stop the sound once it no longer needs to play, thus I'm using a speaker instead. The entity probably spawns but the sound cannot be heard. I couldn't find any function to set the sound so I just used setKey, however this doesn't seem to be enough. What am I missing please?

entity my_sound;
my_sound = sys.spawn("speaker");
my_sound.setKey("s_shader", "eerie01_loop");
my_sound.setOrigin($player1.getEyePos());
my_sound.bind($player1);

Something else I'm going to need: I would like to know how I can find an entity of a given type within a given radius from a point or a bounding box. Order isn't important, any entity can be picked at random as far as I'm concerned. I tried playing with $ent.findActorsInBounds('-256 -256 -256', '256 256 256') but only got weird and random results... can I tell it what classname I want, ideally without having to call it on another entity on the map? If that doesn't work then how would I loop through all entities on the map then check the distance and pick the closest one? For what I want the algorithm should detect items near the player... loot objects would do as well as tools / ammo / readables / etc.

Also I really need to see an example of how to make the player faster and able to jump higher; $player1.setHinderance() only allows me to lower the walk speed, using values over 1 or negative values don't allow you to go faster instead. People are saying that an implementation of the speed potion exists and was posted on this forum, but I searched and can't find it anywhere... please link me to the thread so I can check out its code.

Link to post
Share on other sites

Regarding the sound: Instead of creating a speaker via script, you could create the speaker in a seperate (e.g. where the start-weapons and items are stored) and move it to the player position, when you need the sound. When  the sound should stop, you could move it back to its former location. That way, you can have the speaker on repeat all the time or you could handle it like you would any other speaker.

Regarding the speed potion:

 

By the way: If you are searching for somethin in the forums, I would recommend to use google with a "site:forums.thedarkomod.com" before the term you are searching for. This limits the google search to the forums and the google algorithm is way better than the search function of the forum itself. In this case it was the second hit of the search.

Link to post
Share on other sites

Never thought of using Google to search a forum... also I don't use Google to avoid being spied on, I default to DuckDuckGo. That thread offers exactly the info I needed! So to boost the player speed you use something among the lines of:

vector boost = $player1.getMove() * '10 10 1';
$player1.applyImpulse($player1, 0, $player1.getOrigin(), boost);

I haven't tested it yet but if it works that should take care of that. Please let me know about finding entities of a given type within a certain radius, still don't know where to start there. The sound isn't urgent for what I'm doing for now.

Oh, and another important thing I need: How do I know if the player is crouching?! The script reference has no function related to crouch, though I can probably access that via a player variable.

It would also help my plan if I could read and modify the player's breath. Can I at least set a flag that makes the breath system behave as if the player is underwater and suffocating even when they aren't?

Update: Found the flags to check the player's movements: $player1.AI_CROUCH, $player1.AI_RUN, $player1.AI_JUMP, $player1.AI_CREEP, $player1.AI_ONGROUND. However if I attempt to use them like that I get unknown value errors! Other parts of the player script use this though, why doesn't it work in my case?

Update 2: Also found how to make a custom GUI follow the HUD settings... just use "gui::HUD_Opacity" and "gui::iconSize" in your definition :)

Edited by MirceaKitsune
Update
Link to post
Share on other sites

There's a script herethat identifies all entities on the map that meet a certain criterion. You may also ask @kingsal
what method he ended up using to check which entities are within a certain volume, he had asked that same question here a few months ago.

Modifying the player's breath: that'd be a case for the breath potion. Alternatively look at the beta thread for ERH's Seed of Lodestar, he's made a diving suit script which automatically regenerates breath. I recall a discussion of using the breath system outside of water, i.e. room with gas, but it didn't seem to be natively supported.

Sounds started with startSound should be looping if the soundshader contains a looping flag. stopSound should stop it, just need to call on the same channel as the one it was started on. Alternatively, if the spawned speaker doesn't start playing you might need to do some more, i.e. trigger it (possibly one frame later), set s_looping & s_maxradius/s_minradius, precache the shader on the speaker.

As HMart points out, and as we saw with AIs, AI_ flags only work if the entity has been defined as the correct type of entity, i.e. ai or player. The player script was probably done as a scriptobject, so the definition wouldn't be visible to an external script.

  • Like 2
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...