Uni Posted August 1, 2016 I have another question regarding decorate stuff. I've been into it in the past couple of days, learning how to use it mostly through reverse-engineering from high quality mods with rich decorate stuff and I made a decent weapon mod with some cool stuff but there are things that I'm still not sure about. Anyways to my question, is it possible for the player to make a special sound when he *picks a weapon for the first time*, you know when he grins like a crazy marine.I want to make a Heretic style laugh sound but I don't want it to apply on repeatable pickup like shotguns and chain guns or even multiple placed weapons, just when the player grins when he acquired a new weapon. 0 Share this post Link to post
Burktross Posted August 1, 2016 scifista42 said:Firstly, the very first tic that an actor executes right after being spawned, never executes its action even if it has one, therefore "Thing_Hate(0,0,0)" doesn't get called. Secondly, both the first "0" and the second "0" refer to the actor itself (who is the activator), not to the player. So it would not make the actor target the player even if it was called - unless you gave a specific TID to the player (in an ENTER script) and used that TID in this Thing_Hate. That's because AAPTR_PLAYER1 is not player1's TID, it's a pointer. GetActorX doesn't accept pointers, just TIDs. Either give a specific TID to the player in an ENTER script, or use "SetActivator" with "AAPTR_PLAYER1" as the second parameter and only then use "GetActorX(0)" to get the player's coordinate (after you've already got the actor's coordinates). I amended the script accordingly:actor AmbientDaemon 16001 { -SOLID -Shootable -NoPain -NoBlood +LOOKALLAROUND +Float radius 16 height 40 States { Spawn: EGGY A 5 EGGY A 1 Thing_Hate(0, 1000, 4) EGGY A 1 EGGY A 5 Goto See See: EGGY A 1 EGGY A 1 Thing_Hate(0, 1000, 4) EGGY A 1 A_NoBlocking EGGY A 1 A_JumpifCloser(512, "Check") // Checks if the player is within 512 // Ignore me // EGGY A 5 A_JumpifInTargetLOS("Daemon", 0, JLOSF_DEADNOJUMP | JLOSF_CLOSENOJUMP | JLOSF_NOSIGHT, 512, 256) // Loop Check: EGGY A 1 EGGY A 1 A_SpawnItem("Xenohunter", 0, 1, 0) // Debug script to check if line 19 was triggered EGGY A 1 A_JumpifCloser(256, "See") //Aborts if player is in the minimum range, 256 EGGY A 1 A_JumpIfInTargetLOS("See", 0, JLOSF_DEADNOJUMP, 512) // Aborts if player is in eyeshot goto Spawner Spawner: EGGY A 1 A_SpawnItem("Facehugger", 0, 1, 0) // Debug script to check if lines 25 and 26 were NOT triggered. EGGY A 400 Goto see Pain: EGGY A 1 A_Pain Goto Spawn Death: TNT1 A 0 A_SpawnItemEx("XenSplatter",random(-16,16),random(-16,16),random(-16,16),random(0,0.1),random(0,0.1),random(-1,1),random(0,359)) TNT1 A 0 A_SpawnItemEx("XenSplatter",random(-16,16),random(-16,16),random(-16,16),random(0,0.1),random(0,0.1),random(-1,1),random(0,359)) TNT1 A 0 A_SpawnItemEx("XenSplatter",random(-16,16),random(-16,16),random(-16,16),random(0,0.1),random(0,0.1),random(-1,1),random(0,359)) TNT1 A 0 A_SpawnItemEx("XenSplatter",random(-16,16),random(-16,16),random(-16,16),random(0,0.1),random(0,0.1),random(-1,1),random(0,359)) TNT1 A 0 A_Scream EGGD ABC 6 A_NoBlocking EGGD C -1 Stop } } With a player TID assigned by the following ACS Script "PlayerTidDaemon" Enter { Thing_ChangeTID(0, 1000 + PlayerNumber()); // This assigns the TID } I can confirm that my player entity is assigned a TID with a in map trigger that prints the activator TID, which would, as expected, read 1000. The script, however, still doesn't call the "Check" state. 0 Share this post Link to post
scifista42 Posted August 1, 2016 I'm not sure why it doesn't work, but try using A_CheckRange instead of A_JumpIfCloser. You may omit Thing_Hate, because A_CheckRange should work even if the actor doesn't target the player. Beware that A_CheckRange jumps if the actor is further than the given distance from the player, as opposed to being closer than the distance. You need ZDoom version 2.8.1 or later, or an appropriately advanced version of GZDoom, to be able to use this function. 0 Share this post Link to post
scifista42 Posted August 1, 2016 Uni said:is it possible for the player to make a special sound when he *picks a weapon for the first time* Define the weapon's pickup as a CustomInventory item separate from the weapon itself. Make sure that this pickup item will be placed/spawned in maps, not the weapon itself. Define your custom sound in SNDINFO. DECORATE:actor MyCoolWeapon : Weapon { ... // definition of your weapon } actor MyCoolWeaponPickup : CustomInventory { Inventory.PickupSound "" States { Spawn: SHOT A -1 stop Pickup: TNT1 A 0 A_JumpIfInventory("MyCoolWeapon",1,"NoCoolSound") TNT1 A 0 A_PlaySound("MyCoolWeaponPickupSound",0) TNT1 A 0 A_GiveInventory("MyCoolWeapon",1) stop NoCoolSound: TNT1 A 0 A_PlaySound("misc/w_pkup") TNT1 A 0 A_GiveInventory("MyCoolWeapon",1) stop } } SNDINFO:MyCoolWeaponPickupSound LUMPNAME // LUMPNAME is the name of the sound lump in the wad 0 Share this post Link to post
Agentbromsnor Posted August 1, 2016 scifista42 said:Of course it is the same, you'll just use "velx" instead of "vely". :) Just to clarify: See: TNT1 A 0 A_JumpIf(vely<0,"MovingLeft") Goto see Does the TNT1 A 0 sprite-frame here need to contain an actual sprite? I'm trying to get an understanding of what everything does so I don't end up mindlessly copy-pasting. :P 0 Share this post Link to post
scifista42 Posted August 1, 2016 "TNT1 A" is a special name that means "no sprite". If the frame duration wasn't 0, the actor would be invisible during this frame. But because the frame duration is 0, it doesn't matter which sprite is there, as it would never be rendered anyway. Even if it doesn't matter, DECORATE modders often use "TNT1 A" on 0 duration frames for DECORATE logic such as giving / taking / checking inventory and state jump functions. That way, you can look at the code and easily differentiate actual animation frames from support logic frames by looking at the 4-letter prefix name. 0 Share this post Link to post
Agentbromsnor Posted August 1, 2016 Interesting! That's good to know! Another thing that popped into my mind: in the context of a player-actor, what does the "see" state actually stand for? 0 Share this post Link to post
scifista42 Posted August 1, 2016 Player stands still -> engine automatically selects Spawn state. Player moves -> engine automatically selects See state. Player fires a weapon -> engine automatically selects Melee or Missile state. (this is, however, not as easy as "melee weapons select Melee state, ranged weapons select Missile state" - Melee seems to be re-selected on every weapon frame, and Missile seems to be selected only when a muzzle flash animation starts) Player receives damage -> engine automatically selects Pain state with a probability given by his PainChance. Player dies -> engine automatically selects Death or XDeath state. (depending on how much damage he received by the last hit that killed him) 0 Share this post Link to post
Agentbromsnor Posted August 1, 2016 That's great to know! Thanks a ton! 0 Share this post Link to post
Agentbromsnor Posted August 1, 2016 I've been looking at this article, in order to mirror my sprite to walk to the left: http://zdoom.org/wiki/Creating_new_sprite_graphics If I understand this correctly, I would still have to create new sprite-lumps in order to mirror them? Is there are DECORATE function for this? I could just duplicate my sprite-frames and mirror them in SLADE3, but I'd like to learn this the best way I can. 0 Share this post Link to post
scifista42 Posted August 1, 2016 Mirroring, in the context of sprite naming conventions, is a way to define 2 sprite frames as sharing the same graphic lump, just mirrored. Suppose you have a single graphic lump named "ABCDEgFh" in your wad. "ABCD" is a sprite prefix, "E" and "F" are frame letters, and "g" and "h" are rotation numbers. Just the mere presence of this lump in the wad defines 2 frames/rotations: "ABCD E", displaying when the actor is being viewed from rotation "g", and "ABCD F", displaying when the actor is being viewed from rotation "h". When rendered ingame (which pre-supposes that the actor is in a state with the appropriate sprite and frame AND is viewed from the appropriate rotation), "ABCD E" will look like the graphic normally does, and "ABCD F" will look like the graphic flipped horizontally. This concept is absolutely unrelated to DECORATE. It's all about file size efficiency of the wad file and memory usage efficiency of the running engine. 0 Share this post Link to post
Agentbromsnor Posted August 1, 2016 So if I understand this correctly, this is only related to which side the sprite is being viewed from? Should I look into using this for my player, or should I opt for a mirrored sprite-set instead? 0 Share this post Link to post
scifista42 Posted August 1, 2016 Agentbromsnor said:So if I understand this correctly, this is only related to which side the sprite is being viewed from? No. Sprite graphic mirroring and sprite frame rotations are also 2 completely separate and unrelated concepts. Here is an example of how you can use mirroring for your advantage in your particular project: (assuming you will use the setup proposed in this post) Let's say you will have a sprite of the player looking right. Give it a name "PLAYA0B0". This will define 2 frames: "PLAY A" when viewed from any rotation, and "PLAY B" when viewed from any rotation (rotation number 0 means looking the same from all sides). Then, in DECORATE, define your player's moving-right animation using "PLAY A" frame, and define his moving-left animation using "PLAY B" frame. The "B" frame will look like the "A" frame mirrored. If you need more frames to use in your animations, use more PAIRS OF letters for each frame and its mirror frame. Each PAIR OF letters/frames will need only one graphic lump. 0 Share this post Link to post
Agentbromsnor Posted August 1, 2016 So, the first sprite-name would be PROTA0B0 in my case, but how would the second sprite-name look, and how would I define it in DECORATE without the engine confusing it for the second sprite facing right instead of left? 0 Share this post Link to post
scifista42 Posted August 1, 2016 Agentbromsnor said:So, the first sprite-name would be PROTA0B0 in my case, That's all you need to make it work.Agentbromsnor said:but how would the second sprite-name look, There won't be any second sprite.Agentbromsnor said:and how would I define it in DECORATE without the engine confusing it for the second sprite facing right instead of left? The engine already knows about it by reading the first sprite's name. 0 Share this post Link to post
Agentbromsnor Posted August 1, 2016 I'm confused now... actor PlayerActor : PlayerPawn { Speed 1 Health 100 Radius 16 Height 56 Mass 100 Player.DisplayName "Eric" states { Spawn: PROT A 1 PROT B 1 PROT C 1 PROT D 1 loop See: TNT1 A 0 A_JumpIf(velx<0,"MovingLeft") PROT A 1 PROT B 1 PROT C 1 PROT D 1 Goto see MovingLeft: PROT A 1 PROT B 1 PROT C 1 PROT D 1 Goto see } } This is the DECORATE for my player actor now. How would I use the mirrored frame here in terms of syntax? You can see that PROT B is already defined here, which is the second frame in the animation from the right side. 0 Share this post Link to post
scifista42 Posted August 1, 2016 Agentbromsnor said: See: TNT1 A 0 A_JumpIf(velx<0,"MovingLeft") PROT A 1 PROT B 1 PROT C 1 PROT D 1 Goto see MovingLeft: PROT A 1 PROT B 1 PROT C 1 PROT D 1 Goto see This is the DECORATE for my player actor now. How would I use the mirrored frame here in terms of syntax? You can see that PROT B is already defined here, which is the second frame in the animation from the right side. You can't make use of different rotations, because your player is always viewed from the same angle. Therefore, if you need to differentiate "right" animation from "left" animation, you need to use different frames for each: See: TNT1 A 0 A_JumpIf(velx<0,"MovingLeft") PROT A 1 PROT B 1 PROT C 1 PROT D 1 Goto see MovingLeft: PROT E 1 PROT F 1 PROT G 1 PROT H 1 Goto see Once again, please note that a sprite frame in Decorate and ingame IS SOMETHING DIFFERENT than a sprite lump in the wad file. Thanks to the very concept of "mirroring", one sprite lump can define 2 different frames, and the relation between these 2 frames is arbitrary. Your wad would contain only the following 4 lumps:PROTA0E0 PROTB0F0 PROTC0G0 PROTD0H0 All 4 of them would depict the player looking right. 0 Share this post Link to post
Agentbromsnor Posted August 1, 2016 Ooooh now I understand. So as long as the sequential mirrored frame-letters are different from the first one, everything should be good? :o EDIT: It seems to work pretty well! :D Thanks for the detailed explanation. Hmm. The player moving animation does look a bit strange since the standard Doom movement is a bit "slidey" (you have to wait until the player stops sliding, before the animation to the opposite side starts). I can't find any related flags about this on the ZDoom wiki. Do I have to dive into ACS to fix this I wonder? :o EDIT: I'm sorry, I don't mean to use this thread as my personal journal. I will refrain from posting more questions until I have a more serious issue. 0 Share this post Link to post
scifista42 Posted August 1, 2016 The "slidey-ness" is related to friction. You could increase the actor's Friction, but that would make him move slower as well. If you want the player (the ingame actor) to appear to have changed his direction as soon as the player (the person who plays the game) presses the appropriate button on the keyboard, ACS is necessary. Particularly the function GetPlayerInput. If you resort to this, feel free to forget about the "velx<0" thing. Does it really look that bad ingame when the player doesn't appear to change his direction until he actually starts moving in that direction? I thought it looked OK in the platform games that I've played. 0 Share this post Link to post
Agentbromsnor Posted August 1, 2016 scifista42 said:The "slidey-ness" is related to friction. You could increase the actor's Friction, but that would make him move slower as well. If you want the player (the ingame actor) to appear to have changed his direction as soon as the player (the person who plays the game) presses the appropriate button on the keyboard, ACS is necessary. Particularly the function GetPlayerInput. If you resort to this, feel free to forget about the "velx<0" thing. Does it really look that bad ingame when the player doesn't appear to change his direction until he actually starts moving in that direction? I thought it looked OK in the platform games that I've played. Yeah, it's actually not that bad looking by itself, though I guess I'm just picky. I also just thought about another method; if I could fetch a variable for when the player releases either one of the two movement keys, I could perhaps insert a animation of the player grinding to a halt (much like Jazz Jackrabbit does, I think?). Thanks! 0 Share this post Link to post
scifista42 Posted August 1, 2016 Agentbromsnor said:if I could fetch a variable for when the player releases either one of the two movement keys, You can do that, but only via ACS. Note that it is possible to call ACS from DECORATE, and you can write your script to just return the desired variable as its return value, then use the value in a DECORATE expression. 0 Share this post Link to post
Agentbromsnor Posted August 2, 2016 scifista42 said:You can do that, but only via ACS. Note that it is possible to call ACS from DECORATE, and you can write your script to just return the desired variable as its return value, then use the value in a DECORATE expression. I see! Do you happen to have a good example of mixing ACS with DECORATE like that? Would I still be able to use my mirrored sprite-frames? 0 Share this post Link to post
scifista42 Posted August 2, 2016 Agentbromsnor said:I see! Do you happen to have a good example of mixing ACS with DECORATE like that? Go by the example on this page.Agentbromsnor said:Would I still be able to use my mirrored sprite-frames? Why wouldn't you? MIRRORING IN SPRITE NAMES IS UNRELATED TO DECORATE. If your wad contains a sprite lump named "PROTA0E0", it's functionally 100% equivalent as if it contained 2 sprite lumps, one named "PROTA0" and the other one named "PROTE0", and the latter one was a horizontally flipped version of the former one. DECORATE wouldn't notice any difference. The difference is that your wad will have smaller file size and the running engine will use less memory, thanks to the fact that 2 sprite frames were packed into 1 graphic lump. Also, using 2 distinct animations for walking right and walking left could be avoided by using A_SetScale with a positive value if the player was moving right and a negative value if he was moving left. Then you wouldn't need the frames E-H at all, and the MovingRight and MovingLeft animations would share not only the same frames (letters A,B,C,D), but also the very same states (no need to write them twice in the DECORATE). As in: See: TNT1 A 0 A_JumpIf((some condition determining player's direction),"MovingLeft") TNT1 A 0 A_SetScale(1.0) goto MovingAnim: MovingLeft: TNT1 A 0 A_SetScale(-1.0) MovingAnim: PROT A 1 PROT B 1 PROT C 1 PROT D 1 Goto see Now, "A_SetScale" IS a way to mirror graphics via DECORATE, as opposed to mirroring them via sprite names. I've only thought of this method now. It seems better than the one with 2 distinct frame sets and distinct states for each animation, but only if you want ALL the left-moving frames to be EXACT mirrors of the right-moving ones. 0 Share this post Link to post
A2Rob Posted August 2, 2016 Anyone know how to change the color of the BFG impact texture? 0 Share this post Link to post
scifista42 Posted August 2, 2016 A2Rob said:impact texture Do you mean the sprites of the exploding BFG projectile that briefly disappear, or the decals that get printed onto the wall and stay there? 0 Share this post Link to post
A2Rob Posted August 2, 2016 Do you mean the sprites of the exploding BFG projectile that briefly disappear, or the decals that get printed onto the wall and stay there? The sprites that briefly disappear. 0 Share this post Link to post
scifista42 Posted August 2, 2016 And the still-flying BFG ball should stay green? Did you already recolor it somehow? If you used custom sprites for the See animation of the projectile, why don't you use custom sprites for its Death animation too? You ARE talking about sprites in the Death animation of the projectile actor, and NOT about the decals that appear flat on the wall, right? 0 Share this post Link to post
A2Rob Posted August 2, 2016 You ARE talking about sprites in the Death animation of the projectile actor, and NOT about the decals that appear flat on the wall, right? I'm assuming this is a decal 0 Share this post Link to post
scifista42 Posted August 2, 2016 Yes, it is. Decals are defined in DECALDEF. See the DECALDEF within "zdoom.pk3" to find out which decal belongs to the BFG and which graphic(s) it uses. Then, in your wad, make your own DECALDEF and define your own decal using the same graphic(s) and use the "colors" command to recolor it. Then assign the new decal to the BFG ball, either via DECALDEF ("generator" command) or via DECORATE ("Decal" actor property). 0 Share this post Link to post
Agentbromsnor Posted August 2, 2016 scifista42 said:Go by the example on this page. Why wouldn't you? MIRRORING IN SPRITE NAMES IS UNRELATED TO DECORATE. If your wad contains a sprite lump named "PROTA0E0", it's functionally 100% equivalent as if it contained 2 sprite lumps, one named "PROTA0" and the other one named "PROTE0", and the latter one was a horizontally flipped version of the former one. DECORATE wouldn't notice any difference. The difference is that your wad will have smaller file size and the running engine will use less memory, thanks to the fact that 2 sprite frames were packed into 1 graphic lump. Also, using 2 distinct animations for walking right and walking left could be avoided by using A_SetScale with a positive value if the player was moving right and a negative value if he was moving left. Then you wouldn't need the frames E-H at all, and the MovingRight and MovingLeft animations would share not only the same frames (letters A,B,C,D), but also the very same states (no need to write them twice in the DECORATE). As in: See: TNT1 A 0 A_JumpIf((some condition determining player's direction),"MovingLeft") TNT1 A 0 A_SetScale(1.0) goto MovingAnim: MovingLeft: TNT1 A 0 A_SetScale(-1.0) MovingAnim: PROT A 1 PROT B 1 PROT C 1 PROT D 1 Goto see Now, "A_SetScale" IS a way to mirror graphics via DECORATE, as opposed to mirroring them via sprite names. I've only thought of this method now. It seems better than the one with 2 distinct frame sets and distinct states for each animation, but only if you want ALL the left-moving frames to be EXACT mirrors of the right-moving ones. Hmm, that's also a good alternative. I would have to look into the A_JumpIf condition that actually looks at when the player presses the button, instead of when the X velocity reaches a positive or negative value. Something unrelated: because I'm using my own IWAD, the game shows a strange looking block (similar to a HOM) where the status-bar would be. Now, I've already looked into SBARINFO, but I'm kind of torn between two options here: I could try and remove the status-bar (if possible), and hopefully get rid of the - and + screen size increase thing which has no place in my game. Alternatively, I could also script my own little HUD using ACS, which should be pretty easy to do with "GetActorProperty". I'm actually not sure if there's a way of making a subtle HUD using SBARINFO without it being a bar at the bottom of the screen. 0 Share this post Link to post