Jump to content
The Dark Mod Forums

Spooks

Member
  • Posts

    612
  • Joined

  • Last visited

  • Days Won

    38

Posts posted by Spooks

  1. Suppose I have four different brushes I put into a layer, and then I want to clone them 100 times around the map while still being able to select each one of those 100 groups. That's 100 superfluous layers right there. Selection sets are the same deal, but even worse, since you have to go through a typed list and there's no way to delete an individual selection set.

     

    If you wanted just the same brushes over and over, you obviously export them as a model, yes, but the biggest drawback is that those things are entities and not worldspawn, and there is no way to turn them back to worldspawn without inlining, which spits them back out without collision, among other caveats already discussed in the topics I linked.

     

    Layers are for higher-level structuring while func_group is (supposed to act as) low-level organization. I wouldn't even be complaining about the prospect of 100 layers if DR's layer window had some sort of folder structure in, because even that would alleviate some of the problem, if in a non-elegant way. (Layers aren't exclusionary so this is already sort of present, but nowhere in the GUI) Right now the way selection is in DR is Filters > Regions > Layers > Selection Sets > Hide/Unhide. None of those quite fit in the niche that something like func_group would fill. edit: forgot to mention prefabs, we can count those in too, but again, not quite the same

     

    We can split hairs about how useful grouping with func_group would be in practice: limited to brushes and not models, same inherent problems func_statics of brushes have with their origin points/rotation, limited usage scenarios - even though you could say the same about selection sets and Region view tbh - and so on. Regardless, I still don't know why it's broken and if it's a trivial enough fix to get it going I think it definitely should be resurrected from the dead.

  2. I've browsed through several of the topics here mentioning the func_group entity. Basically, it's supposed to group brushes in DR like func_static does, but at compile time it turns them back from func_group to worldspawn. The one mention of it from the first page of Google is from a 2006 post on a Doom forum that states func_group was used back in the quake days but it's useless in Doom 3, and the two threads from here confirm it's broken.

     

    My question is, does anybody know why func_group won't convert the brushes at dmap? The functionality is supposed to be in the engine code. I think inlining is okay as it is, but func_grouping could be extremely useful for certain situations where you don't want FS brushes to remain entities in-game, but you still need to group them in DR in some way.

     

  3. Short answer is no, not in a simple manner. There isn't such an AI entity in yet, I actually need something like that too. You can replace the animations and vocal sets of a guard with a zombie's with spawnargs, but I'm not so sure about the vulnerability to holy water.

     

    Thinking about it you can just def_attach some armor pieces to a zombie and sort of approximate the look of a guard. If you need help with def_attaching and attachment points for AI, you can look it up on the wiki. The only thing I think would be hard to do is get a breastplate to look good.

     

    EDIT: Zombie models probably don't have the same def_attach points as regular AI so that's probably out of the question too.

  4. As my first FM is still in the oven I don't have the experience of multiple levels behind me, but I can say that what helped me not quit and keep progressing was building the entire thing in dev textured, blocky brushes first. That way, the sunk cost fallacy kicks in your brain, and it's much harder to quit on an entire, unfinished map than a small, but polished map chunk.

     

    This of course requires that you think up of your whole level first, but! I've had it where I'd worked on other personal projects where I had spent a month thinking of all the cool things that would be in it without attempting any implementation. Finally I went to the SDK and whoops, can't do half of it because of software limitations, there's the entire thing trashed. That's why it's super important to test how feasible your ideas are as soon as possible, rather than spend hours with a notepad.

     

    If you commit to a slow, but iterative process like that, it's important to keep small, achievable goals to keep you motivated. Have a checklist of passes you need to go through: texturing, trim, props, lighting, AI, etc. It's also very useful to section your map into multiple areas so if you get bored or stuck, you can always jump to another one and always keep making progress.

     

    I've been wanting to try and make modular building work, but that's for after whenever this FM gets done. For point number 5, and this is pretty closely related to modular, I'd say "Keep your grid sizes consistent!" I think that even in free building, the old-school way, being tidy with your brushes is extremely important. Don't have one wall be 8 units and another 16, unless there's some real reason for it. Don't have your trim be one third of your wall, that makes tiling the texture correctly a nightmare! Just stuff like that.

     

    I'm a visual type of person, so first thing I'll do is just think of a cool location to be in. Something I, as the player, would enjoy exploring. It could be a house in a city mission, or a nice foyer or banquet hall in a mansion. From there, it's easy for my imagination to spiral out into how the street connecting the house look like, or how the other rooms in the mansion connecting to that hall are like. Then you go from those rooms to the other rooms and you see where this is going. I then think about how to design gameplay around that. I feel this makes it more organic (and constraints are always good to work in), as there's nothing I hate more than being taken out of the simulation and realizing somebody's just making me do timing puzzles with an architectural set dressing.

     

    Story is sort of the same, it's always more fun to put the most bare-bones of themes or just one very specific event in, then go from there. Better to have a central idea that facilitates interesting side-stories than making the player go through the Silmarillion just so they could enjoy your mission. The approach is nice since at its core it keeps the player's motivation simple and grounds the story in their action rather than that of outside forces.

     

     

    • Like 3
  5. One of my objectives isn't completing and I don't know why. It's a simple one: when the player closes a readable, its completion target points to a speaker that plays a sound.

     

    I get this in the console when I close the readable:

     

    "WARNING: Objective System: GeComponentState: Component num 0 out of bounds for objective 16."

     

    Can't find no component num 0 in the spawnargs and the speaker's right next to the readable. Any ideas?

  6. I like Audacity but its ogg exporter doesn't give you any correct kbps option, it seems it just does an average bitrate which is not ideal but hey, at least TDM doesn't outright deny high bitrate files, they're just more space. File -> Export Multiple does allow you to batch export though (even though it's slow as it may ask you to fill metadata info for each exporting file, dunno if there's an option to turn that off).

    • Like 1
  7. If an entity's spawnargs are used by a script (probably the entity's script object), then you can adapt the script to reread them as desired; if the behaviour you're interested in is defined by code in the spawnclass, then you can't change the entity's behaviour after spawn unless the code provides a means of doing that.

    In my case it's changing the conversation arguments inside an atdm:conversation_info, so I guess no go, since it looks to me those things interact straight with the SDK without any script objects.

  8. So the description of setKey says "Sets a key on this entity's spawn args. Note that most spawn args are evaluated when this entity spawns in, so this will not change the entity's behavior in most cases. This is chiefly for saving data the script needs in an entity for later retrieval."

     

    So is there a way to make the entity re-evaluate its script-updated spawnargs at runtime and act differently, or is this just for using entities as variable carriers?

  9. I would guess you need to not rotate around the X and Y axes if the skull is just supposed to look at you laying flat on some surface, rather than on a spike or something. Kind of like a grass sprite vs a lamp glow sprite. Then the tilting would not be present, but of course, that may not be ideal if the skull is supposed to track you on all 3 dimentions rather than on a level field.

  10. I was trying to get to where VanishedOne was going, but also not making the moveable slide around. Instead I created a murder machine.

    vector upabit = '0 0 8';
    	while(1) {
    		vector thingPos  = $thing.getOrigin();
    		vector updatedPos = upabit + thingPos;
    		$thing.setOrigin(updatedPos);
    		sys.waitFrame();
    	}
    

    I suggest you try this piece of code with a heavy moveable, like a crate. Best to unleash it next to some friendly AI.

    PS: Do not attempt to touch the rampaging crate, it makes it angrier.

     

    EDIT: Video footage of the disaster has surfaced.

    • Like 3
  11. Boy do I remember spending hours tweaking cvars in the Crysis console... Yeah it's fun but I dunno how much you can get out of the .cfg file alone, besides AA and AF. The current version of the mod doesn't have too many fancy features implemented like parallax, AO or soft shadows. For AO, I know it can be forced through nVidia Inspector and I've done it before, but never really bothered with doom3/TDM. Worth looking into that.

     

    The way I see it, besides post-process stuff one can always mod in higher res textures and higher poly models if they had the technical know-how. A fan mission author can also lock additional detail behind the "Object Detail" option in the menu, so the higher you set it, the more detail you see. I don't think anyone's heavily done this in their missions, though, since it's probably too much work for little gain, if only a fraction of the players would get to see their work.

  12. When I said 'see frob_action_script', I meant look for a snippet about namespaces; if I'd thought more clearly I'd simply have quoted it:

    I didn't know that, very interesting that you can just put that on the value. I've not had to explicitly specify the map script's namespace when putting a function from there in my frob_action_script spawnargs though. Out of interest do you happen to know how you would call the map namespace in a frob_action_script if you had to? Is it just "my_map_name::my_function"? What's the name of the map namespace, that is. "<map namespace>::<function>"" tells me nothing.

     

    I got it working with scripts in my test map, but

     

    I'd use an invisible reversible objective for this:

    - have 2 potions, success makes the chest unfrobable, failure makes the chest frobable

     

    You'd have to make the potions undroppable to avoid exploits, and you might need to have a delay between each potion handout at the chest to give the objective enough time to react.

    this is a far more user-friendly solution, thank you Dragofer. The only advantage the script approach has is that you don't have to make the potions undroppable, but I wouldn't want them to be for my purposes anyway. I might just adopt that approach for the real map.

     

    As promised, here's how I did it in script:

     

     

    Assuming you have a custom entity definition called "atdm:playertools_duckblood" with a default script object "playertools_duckblood"

     

    in the beginning of tdm_custom_scripts.script:

    //both of these are declared here because both the script object and the map scrip need to access them
    
    float duck_points; //counter
    entity Frob_Glob; //the frobber which has a Frob s/r response and dispenses the potion
    
    /*the getFrobable scriptEvent doesn't work with immediate references (dunno why)
    and you can't immediately reference an entity data type
    so we use this function to fetch the real entity's name*/
    entity fetchFrob_Glob(){
    	Frob_Glob = sys.getEntity("frobglob");
    }
    
    

    then, in myTestMapsName.script:

    entity duck_blood; //the potion entity
    
    void spawnBloodVial(){
    		if (duck_points < 2) {
    		duck_blood = sys.spawn("atdm:playertools_duckblood");
    		duck_blood.addItemToInv($player1);
    		duck_points++;
    		sys.println("Duck point added, currently at "+duck_points);
    		}
    		
    		/*this makes the frobber unfrobable, which is simply cosmetic; it won't dispense potions
    		either way but it looks better if the player can't frob it*/
    		if (duck_points == 2) {
    		Frob_Glob.setFrobable(0); 
    		sys.println("Duck points at max: "+duck_points);
    		}
    		
    }
    
    //the frob S/R on "frobglob" points to this code
    void execute() {
    	fetchFrob_Glob();
    	spawnBloodVial();
    } 

    and then, again, in tdm_custom_scripts.script, the custom script object:

    
    #ifndef __CUSTOM_PLAYERTOOLS_SCRIPT__
    #define __CUSTOM_PLAYERTOOLS_SCRIPT__
    
    /*there is a bunch of cloned code from the playertools_holywater script object here,
    we will just skip that and move to the part where I've made changes*/
    
    void playertools_duckblood::inventoryUse(entity userEntity, entity frobbedEntity, float buttonState)
    {
    	// If we have a previous thread still running, terminate it
    	if (_updateThreadNum != -1)
    	{
    		sys.terminate(_updateThreadNum);
    	}
    
    	// Callback to decrease the inventory stack count
    	userEntity.changeInvItemCount(getKey("inv_name"), getKey("inv_category"), -1);
    
    	// Deduct a duck point, check if the counter's maxed, make frob_glob frobable again if it isn't
    	duck_points--;
    	if (duck_points < 2) {
    		fetchFrob_Glob();
    		Frob_Glob.setFrobable(1);
    		sys.println("Duck points are less than two, frobglob is frobable.");
    	};
    	sys.println("Duck point taken, currently at "+duck_points);	
    	
    	// Play the activate sound
    	userEntity.startSoundShader(getKey("snd_activate"), SND_CHANNEL_ANY);
    	
    	// Swap the waterarrow projectiles
    	userEntity.changeWeaponProjectile(getKey("weapon_name"), getKey("def_projectile_holy"));
    
    	// Start a new script thread for updating the timer and resetting the projectile
    	_updateThreadNum = thread update(userEntity);
    }
    
    #endif
    

     

     

  13. Yeah, frob_action_script would be perfect to carry out the decrement code snippet, but alas, it gets called when the player frobs the potion model to pick it up rather than use it in the inventory. Same for a frob S/R. A player S/R fires when the player holds the potion in their hands. Equip_action_script sounds promising but but does nothing, as I suspect it may only work on weapons.

     

    Different namespaces are definitely the issue when it comes to the script object/map script interaction, and I'm not fully acquainted with how to make them work yet. Hmm, I wonder... If I put a variable at the top of tdm_custom_scripts.script (which gets included in tdm_main), would that make it a global variable that could be accessed (and modified) both through the Script Object and map script namespaces? Will have to investigate tomorrow...

     

    edit: Yes, it does, soon as I get around to it I'll see if I can make this work and if I do, post an example here for posterity.

  14. I got to play through this, the only part I had trouble with was

    finding where the Owner's Room was, since the 1st floor is symmetrical and I was left with the impression there was only one redbrown wood door - the noble's one.

    Otherwise, it was great fun to murder pretty much everyone in the inn including people in their sleep (don't judge my bloodlust)! For feedback, I spotted a couple of black paintings in the room with the blue wallpaper so that skin's probably not included and one of the notes in the delivery room didn't have its frobdistance to 1 and I think that's about it.

  15. I need some scripting help. I want the player to frob, say a sack, then get a potion, easy enough. I also want the player to get no more than two potions and disable frobability of the sack; that's easy too - it's a conditional if statement that increments a counter and some "setFrobable" magic. But, I want whenever the player uses the potion, I want that counter to go down and the sack to become frobable again, so it can dispense more potions, essentially making sure that the player can always get more, but never have more than two at one time without spending them first.

     

    So far I've tried a custom entityDef with a custom Script Object (which is a potion script object clone). I figured, since the frob/equip/used_action_script spawnargs don't work and I couldn't find any scriptEvents that fetched when a player uses a potion/item in their inventory, a script object (and the InventoryUse routine inside it) would be the only way to detect inventory use and decrement the counter from my main map script.

     

    BUT, I have no idea how to make the script object read variables from the map script and send them back (even though the reverse is possible - your map script can read variables from any SO). I would appreciate if someone can tell me if the Script Object approach is a dead end and if there's some scriptEvent I can use that I'm missing.

     

    tl;dr: Help me make an object that gives you consumable items, but stops once you hit a cap, then resumes once you're not at the cap because you've consumed some or all of the items.

  16. You cannot set negative values in the particle editor, something that iirc was possible in 2.0.2. Doesn't work in 2.0.3/2.0.4 pre2. Take any of the recyc_hexdrip particles e.g., specifically the second stages (the water droplet splashes). Their speed is -30 to 9, but the particle editor clamps the first value to 0, and if a mapper clones one of those for a custom particle it will come out wrong.

     

    e: speaking of values being clamped I put an AI tab UI issue like this on the tracker (and thank you greebo for moving that other one, I was dead tired when submitting it and it shouldn't have been in the DR section :wacko: )

  17. Better to check it's not a typo or something like " or ... messing it up

     

    I have to second that " is a reserved character and you have to be careful with it inside strings, I had some frustrations with that. Either escape it, like \" or just type two apostrophes like this ''. The latter is a more foolproof way of doing it.

     

    I know how xdata files are made but still keep to the readable editor. I've seen that bug, it's usually when you've not reloaded xdata. Are you sure you'e replacing "book_handwritten2" in the xdata contents spawnarg rather than the name?

  18. Under ideal circumstances, 1 and 1 should suffice. The mapper shouldn't build off that because their monitor could very well be set up weird though. If you want a baseline for darkness, look to the light gem. At "0.04 0.04 0.04" global ambient light the light gem should be barely lit and completely unlit when crouched.

     

    I've had mine to 1 and 1 but lately my monitor's been giving me trouble and making things darker, so I bump the gamma to 1.2. Generally, when playing at daytime I have to up the gamma as well, since 1 gamma really only works at night with the lights turned off.

    • Like 1
×
×
  • Create New...