Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
baja blast rd.

*** The "ask a miscellaneous editing question" thread ***

Recommended Posts

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.

Share this post


Link to post
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.

Share this post


Link to post

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.

Share this post


Link to post
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

Share this post


Link to post
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

Share this post


Link to post

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

Share this post


Link to post

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?

Share this post


Link to post

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)

Share this post


Link to post

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.

Share this post


Link to post

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.

Share this post


Link to post

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?

Share this post


Link to post
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.

Share this post


Link to post

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?

Share this post


Link to post
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.

Share this post


Link to post

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.

Share this post


Link to post
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.

Share this post


Link to post

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.

Share this post


Link to post

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.

Share this post


Link to post
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!

Share this post


Link to post
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.

Share this post


Link to post
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?

Share this post


Link to post
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.

Share this post


Link to post
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?

Share this post


Link to post

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.

Share this post


Link to post

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?

Share this post


Link to post

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

Share this post


Link to post

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

Share this post


Link to post
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.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×