Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Knas

What's wrong with this Decorate spawner/actor?

Recommended Posts

I have tried maaaaany variations of this script, each behaving a bit different but never in a way I want.

First problem is that when the leaf hits the ground its velocity becomes 0. This might be because of the missile flag, but how do I avoid that(I want it to keep its velx when hitting ground)? The reason I use missile is because I want it to enter death when it hits something. I have seen other predefined spawners in ZDoom use this and those works fine without the above problem...

The second problem is that once they have entered death their angle becomes messed up. If they trigger the x push in death state they move at angle 0, even if I set the angle manually with a variable that uses its initial angle. Even stranger is that a trace even says it still has its parents angle. They also, in very rare occasions, get insane velocity. I have no clue here.

Third problem is that the leaf is removed way before its kill counter reaches 20. It didn't use to but now it does for some reason. I have increased the spawn rate a lot so is there some max amount that can be spawned at the same time?

Spoiler

ACTOR LeafS 7000
{
  +NOBLOCKMAP
  +NOSECTOR
  +INVISIBLE
  States
  {
  Spawn:
   	TNT1 AA 10 A_SpawnItemEx("CLeaf1", random(-128, 128), random(-128, 128), random(56, 72), 0.8, 0, 0, 0, 0, 128)
    //TNT1 AA 1 A_SpawnItemEx("CLeaf2", random(-128, 128), random(-128, 128), random(64, 128), random(1, 3), 0, 0, 0, 0, 128)
	//TNT1 A random(60, 150)
	loop
  }
}

ACTOR CLeaf1
{
  Radius 2
  Height 4
  Gravity 0.1
  //scale 0.5
  +NOBLOCKMAP
  +MISSILE
  +NOTELEPORT
  +DONTSPLASH
  var int user_killleaf;
  
  
  States
  {
  Spawn:
    LEF1 A 0 nodelay A_SetScale(frandom(0.5, 0.8))
  Falling:
    LEF1 ABC 4 
    LEF1 D 0 A_Jump(160, 2)
    LEF1 D 4 A_ChangeVelocity(velx, vely, random(1, 2))
    LEF1 EFG 4
    LEF1 H 0 A_Jump(160, 2)
    LEF1 H 4 A_ChangeVelocity(velx, vely, random(1, 2))
    LEF1 IAB 4
    LEF1 C 0 A_Jump(160, 2)
    LEF1 C 4 A_ChangeVelocity(velx, vely, random(1, 2))
    LEF1 DEF 4
    LEF1 G 0 A_Jump(160, 2)
    LEF1 G 4 A_ChangeVelocity(velx, vely, random(1, 2))
    LEF1 HI 4
    stop
  Death:
    LEF1 D 0 A_SetUserVar("user_killleaf", user_killleaf+1)
    LEF1 D 0 A_JumpIf(user_killleaf>=20, 5)
    LEF1 D 0 A_Jump(192, 2)
    LEF1 D 0 A_ChangeVelocity(1, vely, velz)
    LEF1 D 30 A_ChangeVelocity(velx, vely, frandom(1, 1.5))
	//LEF1 D 0 A_Logint(user_killleaf)
    LEF1 D 0 A_Jump(256, "Falling")
    LEF1 D 60
	stop
  }
}

Share this post


Link to post

For a start, I suggest doing this (changes are bolded and underlined):

  Death:
    LEF1 D 0 A_SetUserVar("user_killleaf", user_killleaf+1)
    LEF1 D 0 A_JumpIf(user_killleaf>=20, Destroy)
    LEF1 D 0 A_Jump(192, 2)
    LEF1 D 0 A_ChangeVelocity(1, vely, velz)
    LEF1 D 30 A_ChangeVelocity(velx, vely, frandom(1, 1.5))
	//LEF1 D 0 A_Logint(user_killleaf)
    Goto Falling
  Destroy:
    LEF1 D 60
	Stop

Because I think jump offset and commenting out states is a bad idea...

Share this post


Link to post

Wait, what actually removes the actor in your example? I thought that only happened at the end of the death state.

Share this post


Link to post

Absolutely nothing is defined by what "state" actors are in, as states are only pointers to frames and thus house no attributes to an actors current behaviour. If an actor is stopped on a finite frame (they have no next frame to go to), they are removed. Plain and simple.

Share this post


Link to post
Knas said:

Wait, what actually removes the actor in your example? I thought that only happened at the end of the death state.

No; you're making an assumption born from the way the code is written, but it's baseless when you know the way the code is interpreted by the engine.

For example, there is no "end of the death state": each state is atomic. Here is the death state:

  Death:
    LEF1 D 0 A_SetUserVar("user_killleaf", user_killleaf+1)
That's all! Anything that arrives after is not the death state. (That's why personally I prefer talking about "state sequences" to describe a whole block of states from the label to the last Goto/Loop/Wait/Stop instruction.) Also a Goto/Loop/Wait/Stop instruction is not, in itself, a state: it merely modifies the definition of the previous state. A state is made up of a sprite name, a frame letter, a duration, and a pointer to the next state, at a minimum. (It can also have flags, such as bright, and action functions; but those are optional.) ZDoom implicitly will set the "next state" pointer to the next state to be defined, because that's something that is logical for human coders, but in reality it could be anything, and the goto/etc. functions are there for that.

An actor will be removed whenever it encounters a stop instruction. Stop says that it has no other state to go to because it stops existing. You can put Stop in the Spawn state if you want.

So, when I see this:[code] LEF1 D 0 A_JumpIf(user_killleaf>=20, 5)
LEF1 D 0 A_Jump(192, 2)
LEF1 D 0 A_ChangeVelocity(1, vely, velz)
LEF1 D 30 A_ChangeVelocity(velx, vely, frandom(1, 1.5))
//LEF1 D 0 A_Logint(user_killleaf)
LEF1 D 0 A_Jump(256, "Falling")
LEF1 D 60
stop
[/ccode]
I see a problem. A_JumpIf will jump five states ahead, okay? Well. Let's do this.
A_Jump(192) is +0 since it's the state you'd get to if you weren't jumping. It's skipped.
A_ChangeVelocity(1) is +1. Skip.
A_ChangeVelocity(velx) is +2. Skip.
//A_LogInt is a comment, so it's always skipped anyway.
A_Jump(256) is +3. Skip.
LEF1 D 60 is +4. Skip.
Stop is part of LEF1 D 60, not a separate state, so ignore.
The actor definition stops here. The next state to be defined will be the +5 reached by our A_JumpIf, but unfortunately it'll be in a different actor. It's actually undefined what happens in such a situation. And all that is caused because A_JumpIf was made to jump five offsets when there was a LogInt function; and then LogInt was commented out, removing a state from the actor, but forgetting to update the number of states that have to be jumped. Using a custom state labels is a lot safer, don't hesitate to use them.

The worst that can happen when inserting a state label in a sequence is that you may have to change a final Loop into a Goto (since Loop only goes back to the last parsed label).

Share this post


Link to post

Oh, now I understand. Thanks for the detailed explanation. :) Will make stuff a lot easier. I now see lots of problems with the code. But if I'm not mistaken that's not how the example in the wiki counts.

Would be nice with a state keyword that has a % chance of skipping the action special though, so you don't need to use jump as much.

Now I need to figure out why it moves at angle 0 when it hits the floor, even when a_logint says the angle is the same as when it spawned. Might have something to do with the missile flag, but I need a way to jump states immediately when it hits something.

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
×