Jump to content
The Dark Mod Forums

MirceaKitsune

Member
  • Posts

    1930
  • Joined

  • Last visited

  • Days Won

    22

Posts posted by MirceaKitsune

  1. 1 hour ago, HMart said:

    In that case you have to code them yourself, like those inside the player object script, if the necessary peace's of information, is available to the script code, that I don't know if it is. 

    I seemingly have the knowledge to do that, unless something more than my experiences with scripting so far is involved. Main problem with that is I'd need to modify a default script, talk with the devs to see if they approve the change, and even if they do wait for the next TDM release (one every 6 - 12 months) so it can be normally used by everyone.

  2. Such great work again! As I want to have the latest version and helping with testing is the least I can do for all your work, I got the installer and am upgrading to the latest beta right now. Will let you know if I find any bugs... for reference I'm testing on Linux (openSUSE Tumbleweed) x64, AMD card running on the free video drivers (amdgpu / Mesa). And as suggested in another post I'm going to enable r_shadowMapSinglePass too and see how much that improves FPS and if without breaking stuff.

    • Like 2
  3. Didn't think mapping could be even further improved, yet this feature sounds like a great way to do it. Thank you for another great idea!

    So if the player modifies the map in DR and saves it, they can automatically alt-tab switch to TDM and see the changes? First issue that pops to mind is how adding or removing areas may cause the player to get stuck inside walls or left floating / falling in the void, unless there's a smart way to know how to reposition them. The rest I'm assuming solutions have been found for... like caching newly added textures in realtime, I know the engine wants every asset to be loaded at map start.

    Something that would be equally useful, perhaps even more if not as much as this change: Could DarkRadiant offer a button to launch TDM on the map currently being edited? So each time you want to test you don't have to manually open TDM then type the name of the map in the console, just hit one button and it all happens for you.

  4. 7 hours ago, Destined said:

    It is. You can find it in DR under Player_tools (atdm:playertools_breath_potion). It uses the script of the health potion, but has the heal type air. This is defined the def-file tdm_healing.def. I hope this helps.

    Aha... I see it now: So I would use $player1.heal("air", 1) to make the breath restore more rapidly. But how do I decrease the breath down to a certain amount as well... should I use heal with a negative value, a $player1.damage() event I can call with the right damage def, or perhaps there's a flag I can use to make the player act as if underwater? Also I don't even know how to read the breath of the player... we have $player1.getHealth() but no such thing as a getAir().

  5. Much appreciated. The speaker remains unclear so for now I'm not implementing the sound part... it's no emergency anyway. I took note of the entity finding script, just what I needed for what I hope to do next :D

    Using "player self = $player1" will correctly let me access the AI flags; I assumed that $player1 is automatically of type player, but now that I think twice it's indeed a plain entity definition. I can correctly read flags like self.AI_CROUCH now... but when it comes to crouching how can I also set it and tell the player to crouch?

    I looked in the builtin scripts directory but couldn't find any reference for the word "breath". Wasn't the breath potion a default asset? Search isn't helping me and this time I used a search engine too.

  6. 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 :)

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

  8. 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).

  9. 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.

  10. 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.

  11. 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.
  12. I simplified the code a bit and gave alert / evidence states priority over the normal voice (customized with the frob_bark parameter) while alert state checks were fixed so both levels are within normal bounds. Use whichever version of the script you find most fitting for your FM of course.

    void ai_frob(ai self)
    {
    	if(self.AI_DEAD || self.AI_KNOCKEDOUT || self.AI_AlertLevel > 2 || self.isEnemy($player1))
    		return;
    
    	string frob_type = self.getKey("frob_bark");
    	string frob_bark;
    
    	if(self.AI_AlertLevel > 1)
    	{
    		frob_bark = "snd_warnSawEnemy";
    	}
    	else if(self.AI_AlertLevel > 0)
    	{
    		frob_bark = "snd_somethingSuspicious";
    	}
    	else if(self.hasSeenEvidence())
    	{
    		frob_bark = "snd_warnSawEvidence";
    	}
    	else
    	{
    		if(frob_type == "alert")
    			frob_bark = "snd_warnSawEnemy";
    		else if(frob_type == "suspicious")
    			frob_bark = "snd_warnSawEvidence";
    		else if(frob_type == "angry")
    			frob_bark = "snd_admonish_friend";
    		else if(frob_type == "rambling")
    			frob_bark = "snd_relaxed";
    		else
    			frob_bark = "snd_greeting_generic";
    	}
    
    	float look_time = 1 + sys.random(1);
    	self.bark(frob_bark);
    	self.lookAt($player1, look_time);
    	sys.wait(look_time);
    }

    ai_frob.script

    • Like 2
  13. First off thanks to Dragofer and other users who helped with the scripting basics needed to get this done. As a detail for some FM's I plan to make in the future, I wanted to have it possible for friendly AI to be frobbed for idle chatter, causing them to say something random to the player. I first tried with conversation entities but the setup was too ugly and complex, so I decided to do this using one script function. I succeeded with pretty nice results, thus I figured I'd share this for other FM creators to use as well.

    The thing I like most is that it only requires one universal function to be added to your map scripts. Every AI can use it with a simple spawnarg and it doesn't require manually setting any sound shaders: It will automatically work on any character! This means you can use it on a pro guard, a builder priest, a noble woman... each will say the appropriate thing when frobbed. This is done with the power of the ai.bark() call which lets you make the AI speak any action defined in their vocal set (universal across all vocal sets).

    To get it working you only need to add two spawnargs to your AI, with a third optional one for customization (explained below):

    frobable 1
    frob_action_script ai_frob
    frob_bark ...

    frob_bark is optional: If not set the AI will normally greet the player... if alert or having seen evidence of intruders, it will use other lines to inform the player depending on severity. This parameter can be set to the following values to get a custom result:

    • "suspicious": The AI always acts as if it has seen indirect evidence of trouble and warns the player.
    • "alert": The AI always acts as if it has seen an intruder warns the player.
    • "angry": The AI is upset and curses at the player.
    • "rambling": The AI rambles random things when talking to the player (idle lines).

    Finally here's the script itself. It's pretty tiny, most of the code is for choosing the voice to use. Put it on an AI and let me know if you like the result :D

    void ai_frob(ai self)
    {
    	if(!self.AI_DEAD && !self.AI_KNOCKEDOUT && self.AI_AlertLevel < 3)
    	if(self.isFriend($player1) || self.isNeutral($player1))
    	{
    		string frob_type = self.getKey("frob_bark");
    		string frob_bark;
    
    		// Pick what the AI will say when frobbed
    		if(frob_type == "alert")
    		{
    			frob_bark = "snd_warnSawEnemy";
    		}
    		else if(frob_type == "suspicious")
    		{
    			frob_bark = "snd_warnSawEvidence";
    		}
    		else if(frob_type == "angry")
    		{
    			frob_bark = "snd_admonish_friend";
    		}
    		else if(frob_type == "rambling")
    		{
    			frob_bark = "snd_relaxed";
    		}
    		else
    		{
    			if(self.AI_AlertLevel > 2)
    				frob_bark = "snd_warnSawEnemy";
    			else if(self.AI_AlertLevel > 1)
    				frob_bark = "snd_somethingSuspicious";
    			else if(self.hasSeenEvidence())
    				frob_bark = "snd_warnSawEvidence";
    			else
    				frob_bark = "snd_greeting_generic";
    		}
    
    		float look_time = 1 + sys.random(1);
    		self.bark(frob_bark);
    		self.lookAt($player1, look_time);
    		sys.wait(look_time);
    	}
    }

    ai_frob.script

    • Like 3
  14. 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
  15. 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"

     

  16. 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
  17. 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 :)

    • Like 1
  18. Lots of issues, can't find answers to many of them on the Wiki. The script crashes so I can't even test till I fix those.

    First of all the #include argument complains that no file name is given when one is. My tdm_custom_scripts.script contains the line "#include script/ai_frob.script", but this causes the engine to crash with the error "#include without file name". How can there be no file name when I just wrote it in that line?!

    To clarify the last basics: How do I refer to the entity triggering the script function? Your response above implies I use $ai1... as I refer to the player using $player1 I'm assuming this should be it. The other question is how I fetch the spawnarg: Your response suggests I just use the name of the spawnarg in the startSound call, thus I take it that it's converted automatically?

    I'm checking if the AI is dead or alive, which I understand is stored in an AI_DEAD flag. But how do I access this flag? I tried "if(!$ai1.AI_DEAD)" but I get a crash: Unknown value "AI_DEAD". The same thing occurs for "if($ai1.AI_AlertLevel == 0)".

    Even without those checks in place the script won't work yet. The AI entity has spawnargs "snd_talk tdm_ai_pro_greet_guard_to_civilian" and "frob_action_script ai_frob" (my function is "void ai_frob()"). However this code block will not do anything when I highlight and use the AI:

    float sound_duration = $ai1.startSound("snd_talk", SND_CHANNEL_ANY, false);
    float sound_duration_alt = $ai1.startSound("tdm_ai_pro_greet_guard_to_civilian", SND_CHANNEL_ANY, false);
    $ai1.lookAt($player1, sound_duration);

    Update: The above code starts working when I replace $ai1 with $atdm_ai_proguard_1 so something is wrong with that notation. Obviously I want a single common function so I don't want to hardcode AI entity names, what's the proper notation to refer to self? I can hear the sound but sadly there's indeed no lip syncing, however the AI also looks at the player correctly so there is some success.

  19. Thanks for the answers. The biggest problem sounds like the fact that playing a sound on the AI from the script won't handle lip-sync, as well as making sure the voice won't be interrupted if the AI says something else so they don't have two sounds coming out of them. That's a huge limitation! Is there really nothing that can be done here?

    If I'm doing it this way I'd rather not use the conversation editor nor S&R system: I wanted to go that route if this was possible with just entities, with scripting it only feels right if the function can handle everything and I only use spawnargs on the AI to customize it. I'll go ahead and experiment with what was said so far just to get a code basis going... if we figure out the last problems maybe I can post it separately for other creators to use in their FM's too :)

  20. 42 minutes ago, nbohr1more said:

    Hmm...

    I remember this problem from before. I believe the "scale" image program was the workaround:

     

    blend diffusemap

    map scale (models/mapobjects/chairs/kitchenchair/kitchenchair_d, parm0, parm1, parm2, parm3)

    colored

     

    parm0 = red

    parm1 = green

    parm2 = blue

    parm3 = alpha

     

    https://www.iddevnet.com/doom3/materials.html

    map scale (the_texture, parm0, parm1, parm2, parm3): Causes the flames to become completely invisible.

    map scale (the_texture, 1, 1, 1, parm3): No change from not using it at all, you still see the flames popping out of existence instead of fading away.

    Apparently the engine really wants me to use vertexColor, which I cannot as it overrides the colored parameter and causes colorization to stop working. It take it vertex colors are somehow used to tell the particles when to fade... I'd need to somehow set only the alpha channel from it but leave the RGB set by the entity.

  21. I tried using "vertexColor parm3 * 0.4" as suggested by nbohr1more. No idea why that post isn't appearing here any more, I could only see it from an email notification. Sadly it only causes the particles to turn into black boxes without solving the fading issue.

    testing_2020-12-09_22_59_03.thumb.jpg.6749e7b3a920d06dc5a4ad61b3256df8.jpg

     

  22. 3 hours ago, Dragofer said:

    There's the frob_actionscript spawnarg, which calls scripts in your .script files. As far as I'm aware you'd need one script per AI, or a scriptobject that you apply to all AIs concerned.

    Alternatively you can use the S/R system to add a response to frobbing on the AIs which triggers the startconversation entity. Would also want to make this single-use, i.e. by deleting the conversation entity or deactivating the response and deactivating frobability.

    For controlling frobability, I know there are spawnargs for making attached entities un/frobable upon death, but I dont think that exists for the actual AIs. Might be most versatile to just have a script on a 1s loop that checks allegiance + alert state + whether theyve already spoken + AI_DEAD & AI_KNOCKEDOUT booleans of all AIs concerned.

    In the end I feel I prefer this approach, just a script without any S/R. Especially since I don't like having to use so many custom entities for every AI including new conversation definitions: With a script I could define an universal system for interactive talking... if I can pass arguments from the spawnarg I could even customize the voice this way! It would also fix the dead / alert / allied issue... the AI can remain frobable but simply do nothing if the character isn't in a state to talk.

    It seems neither the wiki nor Darkradiant spawnarg docs help me with frob_actionscript. How do I call a script function from it, ideally with the voice passed as a parameter? In this case would I use:

    frob_actionscript mytalkfunction("my_snd_shader")

    I also need to know which checks and functions I can use: First how do I check if the AI is dead? Then how do I check the AI's alert level? Lastly how do I check the AI's team and see if they're allied or neutral to the player? Once all those checks are preformed, how do I tell the AI to play a random voice from the sound shader (eg: tdm_ai_pro_greet_guard_to_civilian) with lipsyncing and everything working? If I'm lucky maybe I can also have the AI turning their head toward the player while talking... if there's such a function please let me know so I can add it to the list! And I should probably not allow the player to make the AI interrupt itself by spamming the use key... can I know when the voice finished playing and tell the script to wait while the character's still talking?

    One more little thing: I plan to use this in campaigns too. IIRC map scripts are defined as mapname.script. Is it possible to have a script universal to a campaign, so that I don't have to copy the script file for each individual map in the list?

  23. I'm trying to prepare a test case for something I plan to have in some FM's: Friendly AI who talk when frobbed... it''s mainly greetings or other conventional voices, just a detail but one I'd like to have. There are quite a few issues I'm not sure how to work around in this, especially without a custom script.

    So far I added my AI, the atdm:conversation_info entity, and the atdm:target_startconversation entity. The conversations themselves are set up, a simple talk action on the actor of the AI. The AI has the flag "frobable 1": I can tell this works as his body lights up when you look at him (not the head but that's probably an internal issue).

    The first problem is how to make the AI trigger the startconversation target when frobbed. Using "target atdm_target_startconversation_1" doesn't work, which is probably for the best as that's meant for path_corner entities. Is there something like a "target_onfrob" spawnflag that I should be using here?

    The last problem would be how I could possibly turn off idle conversations while the AI is alert and obviously when they're dead! Considering I plan to make use of alliance changing too, I'd also like to turn the frob off when an AI is no longer your ally... you don't want clicking on a guard that's going to attack you if he sees you result in a "hello there" right? This part might require scripting if the base AI definition doesn't allow filtering frobbing based on the status of a character.

×
×
  • Create New...