scifista42 Posted November 8, 2016 Gez said:"but if we change it to something that makes more sense now, it's going to break dozens of mods that depend on the not-perfectly-sensical behavior" I never understood why ZDoom developers keep saying things like this to justify weird behavior being kept as default behavior. Why not make it a non-default behavior, possible to be enabled via a compatibility option? The relatively small finite amount of older mods relying on it will have to use this compatibility option to work properly, whereas the potentially infinite amount of future mods will have the benefit of taking "good" functionality for granted, whatever "good" means in the context of the respective feature (it certainly doesn't mean "only good for backwards compatibility with mods relying on a gimmick that this port once introduced by accident"). 0 Share this post Link to post
MaxED Posted November 8, 2016 ...yeah, but are you BAD enough to implement that yourself, or at least make a proper feature request instead of whining about it in random threads? 0 Share this post Link to post
scifista42 Posted November 8, 2016 I'm just asking about the general principle now. What I suggested seems like a natural goal to follow to me, and yet in the long term, ZDoom developers seem to think differently. It doesn't seem like a result of lack of coders and/or awareness of the issues, it seems like they actually prefer inconveniencing the majority of wads and players (by unwanted behavior) over inconveniencing a minority of them (by mere selecting a special option for a special behavior to work). So, why is that? What am I missing? 0 Share this post Link to post
lwks Posted November 9, 2016 So, I'm working on a fix for my mod, and I've already made this code: Death: SPOS H 5 SPOS H 0 { user_spawn = 0; while (user_spawn < 1){ A_SpawnItemEx("ZombieManSpawner",Random(-50, 50),Random(-50, 50),0,0,0,0,SXF_NOCHECKPOSITION); } {return state("SpawnItemEx";)} } SPOS I 5 A_Scream SPOS J 5 A_NoBlocking SPOS K 5 SPOS L -1 Stop So, what I want to do is to check if the actor was sucesfully spawned, and then increment the variable to stop the loop. The problem is that I think I don't know how to use return, and even then GZDoom says this when I try to run: Script error, "Hellspawn.wad:DECORATE" line 127: Unexpected token '{' And yes, this bracket is this one -> "{"return;} What's the problem? 0 Share this post Link to post
Albertoni Posted November 9, 2016 lwks said:Script error, "Hellspawn.wad:DECORATE" line 127: Unexpected token '{' And yes, this bracket is this one -> "{"return;} What's the problem? I'm not seeing that line in your code. That said, I believe the error is here: ("SpawnItemEx";)} Which should be ("SpawnItemEx");} 0 Share this post Link to post
lwks Posted November 9, 2016 It's funny because it says the "{" is on the line 127, but it actually is on the line 128... 0 Share this post Link to post
Empyre Posted November 9, 2016 I would experiment by removing both the opening { and the closing } on line 128. 0 Share this post Link to post
scifista42 Posted November 9, 2016 lwks said:It's funny because it says the "{" is on the line 127, but it actually is on the line 128... Probably because the compiler started looking for a keyword on line 127 after the closing bracket, skipped all whitespaces, reached the opening bracket on line 128, detected an error in syntax, and reported the line where the looking for a keyword has started, 127. It's normal for compilers to report errors on not exactly the same lines where they need to be corrected, because the compiler only understands rules of syntax, not what the programmer wanted to achieve. In C/C++, the superfluous brackets would have been OK, but apparently, they might not be OK in DECORATE. Also, are you sure that you want the actor to jump into a state named "spawnitemex" after finishing the anonymous function, rather than simply continuing the animation with the next state immediately below the anonymous function? 0 Share this post Link to post
Gez Posted November 9, 2016 lwks said:https://s12.postimg.org/vbx0q7nbx/erro.png It's funny because it says the "{" is on the line 127, but it actually is on the line 128... It's probably just because SLADE numbers the lines starting from 1, while ZDoom counts them starting from 0. Try writing some complete nonsense on the very first line, and see if ZDoom reports it as an error on line 0. 0 Share this post Link to post
lwks Posted November 9, 2016 scifista42 said:Also, are you sure that you want the actor to jump into a state named "spawnitemex" after finishing the anonymous function, rather than simply continuing the animation with the next state immediately below the anonymous function? Well, I read in the ZDoom Wiki that I can use return to check if the A_SpawnItemEx successfully spawned an actor, and that's what I want to do, but I should have put the return inside the "while". So...I have to use return without bracketsm cause on the ZDoom Wiki they're all with brackets? Can someone send me a exemple of return? I really have no ideia of how to use this to check if the A_SpawnItemEx was sucessful. 0 Share this post Link to post
scifista42 Posted November 9, 2016 What do you want to happen if A_SpawnItemEx is not successful? You can't just loop it forever during a single tic, because it would never be successful and thus freeze the engine. 0 Share this post Link to post
lwks Posted November 9, 2016 Actually I want to get rid of the SFX_NOCHECKPOSITION. This is causing the actors to spawn inside walls, but the problem is that without it the spawn is like, 5% chance of happening, even though the actor is in a flat and clean surface. That's why I need return, to check if the spawn was successfully and stop the loop (and also to play the Teleport animation but whatever). 0 Share this post Link to post
scifista42 Posted November 9, 2016 The only reason why the spawn may fail is because something is blocking the destination. No randomness/probability is involved. If you call A_SpawnItemEx without SFX_NOCHECKPOSITION and the spawn fails, then if you immediately call it again, it would fail again (guaranteedly if you try to spawn it on the same place, or if you try multiple different places around the actor but none of the places is actually free), and again and again if you keep repeating it - so, if you program the while loop to never stop until success, then it will loop forever, and the engine will be unable to do anything else than repeating this loop, until it eventually freezes and crashes. So, in addition to the wrong syntax, what you're trying to do is also wrong out of principle. Perhaps you could try to use A_SpawnItemEx without SFX_NOCHECKPOSITION a couple times, and if all of them fail, call it finally with SFX_NOCHECKPOSITION as close to the calling actor's position as possible, so that it would be the least likely to spawn inside walls. 0 Share this post Link to post
lwks Posted November 9, 2016 The problem is that the Spawn fail on a clean surface, I really can't believe that a loop won't solve the problem, u sure? I'm talking about a clean surface. Please, just let me test here, and even so, I'd need a return to check if the actor weren't spawned to spawn again using a SFX_NOCHECKPOSITION. (The problem is that I NEED to get rid of SFX_NOCHECKPOSITION, cause it's causing the actors to spawn inside walls). 0 Share this post Link to post
scifista42 Posted November 9, 2016 scifista42 said:The only reason why the spawn may fail is because something is blocking the destination. No randomness/probability is involved. I'm absolutely sure about this. So, looping A_SpawnItemEx only makes sense if you try different places each time. You're apparently doing that (the x and y positions are randomized), so that's OK - but if all places were occupied and you didn't limit the number of iterations of the loop, the loop would never end, which would be bad.lwks said:I'd need a return to check if the actor weren't spawned You don't use "return" to "check" anything. A_SpawnItemEx itself "returns" true if successful and false if not - this doesn't mean you should use the "return" command anywhere. If you wanted a loop going forever until it's successful, you'd do it like this:SPOS H 0 { while(!A_SpawnItemEx(...)) {} } But to avoid looping forever, you'd do it like this instead:SPOS H 0 { user_spawn = 0; while(!A_SpawnItemEx(...) && user_spawn<10) { user_spawn++; } } The latter loop will abort after 10 unsuccessful attempts, for the benefit that the engine won't freeze forever, at the cost that nothing will be spawned. You could also do it so that, after some unsuccessful attempts without SFX_NOCHECKPOSITION, finally give up and use SFX_NOCHECKPOSITION for the last attempt - such a code would have to be structured slightly differently than the above one, but it would certainly be possible. 0 Share this post Link to post
Gez Posted November 9, 2016 lwks said:The problem is that the Spawn fail on a clean surface, I really can't believe that a loop won't solve the problem, u sure? A loop in the same state will not solve your problem because what you need is to move your actor before it tries spawning something again. If you try to do that with a loop in an anonymous function, what will you get? The actor will try to spawn in the exact same place every time so it'll always fail and you'll freeze the game because the actor will never get to leave its state and let the game process the rest of the game world; or it'll succeed on the first try and then looping was useless, wasn't it? What you need to do is set up a loop of several states where the actor moves, tries to spawn something, and if successfully spawned leaves the loop while if spawning failed it goes back to moving. So basically you want this: Death: SPOS H 5 { A_Wander; // Feel free to remove that if it makes it look too weird // to have the corpse move around like this if (A_SpawnItemEx("ZombieManSpawner",Random(-50, 50),Random(-50, 50))) { return state("Death+1"); } return state("Death"); } SPOS I 5 A_Scream SPOS J 5 A_NoBlocking SPOS K 5 SPOS L -1 StopThat way it'll try and try again and again without freezing the game. 0 Share this post Link to post
lwks Posted November 9, 2016 This is impossible, the Spawn occur during the death animation. If you want more, go check my mod on the ZDoom Forum, it's on the first page on the Projects. It's "Hellspawn: Hell's Army" The thing is, whenever an demon dies it spawns other demons. I used the SFX_NOCHECKPOSITION to fix the problem of not spawning, but it's causing the actors to spawn inside walls and stuff...now I sincerely don't know how to fix it... Edit: I'll just link here for the sake of lazyness. https://forum.zdoom.org/viewtopic.php?f=19&t=54133 Edit2: Gez, your code didn't work. Edit3: Tried this: { while(!A_SpawnItemEx("LookZombieMan",Random(-50, 50),Random(-50, 50),Random(-20,20),0,0,0)) { A_SpawnItemEx("LookZombieMan",Random(-50, 50),Random(-50, 50),Random(-20,20),0,0,0); } } Didn't work at all, sometimes it spawns 2, 3 or even 4 ZombieMans, and even, once inside a wall. is there a way for my fix this with advanced programming? (Which skills I do not have) Cuz it seems to me my mod is dead. 0 Share this post Link to post
scifista42 Posted November 9, 2016 You shouldn't be trying to place the spawned monster further from the originating actor than the spawned monster's radius (or the spawned monster's radius + the originating actor's radius), otherwise there will always be a possibility of spawning into walls. Zombieman's radius is 20, so put "Random(-20,20)" into the x and y offset values (or "20 + the originating actor's radius" instead of 20). Then the spawned monsters would tend to be blocked by the originating actor, though. Make the originating actor nonsolid first, by calling NoBlocking on him before the A_SpawnItemEx. Then you still won't be able to spawn more than 1 monster (once one is spawned, it will block the others), but at least one may spawn and be guaranteed to not spawn inside a wall.lwks said:Tried this: { while(!A_SpawnItemEx("LookZombieMan",Random(-50, 50),Random(-50, 50),Random(-20,20),0,0,0)) { A_SpawnItemEx("LookZombieMan",Random(-50, 50),Random(-50, 50),Random(-20,20),0,0,0); } } The A_SpawnItemEx inside the curly brackets is redundant. Even if it succeeds, the loop never finds out about it, therefore will continue looping. The A_SpawnItemEx inside the round brackets is supposed to both do the job of spawning as well as being checked for success. The code still doesn't resolve the threat of an infinite loop, though. 0 Share this post Link to post
lwks Posted November 9, 2016 Well, thank you sir, now it's working: Death: SPOS H 5 SPOS I 5 A_Scream SPOS J 5 A_NoBlocking SPOS J 0 { user_spawn = 0; while(!A_SpawnItemEx("ZombieManSpawner",0,0,0,0,0,0) && user_spawn<100) { user_spawn++; } } SPOS K 5 SPOS L -1 Stop Thing is, the concept of the mod is to spawn two demons, not just one, I think I'll have to put a really good time difference between the two spawns, thing is IF an enemy come closer to the spawn point and block the second spawn? Any sugestions? Also, I'll put your name big and bold on the credits, cause you totally solved the problem for me. Also, this "&& user_spawn<100", what's its use? Is it just to prevent the game freezing? Cause I just deleted it and the mod didn't have any problem. 0 Share this post Link to post
scifista42 Posted November 9, 2016 lwks said:Also, this "&& user_spawn<100", what's its use? It checks the current value of user_spawn and aborts the loop if the value is higher or equal 100. Since you are increasing the value of user_spawn by 1 (user_spawn++) in each iteration of the loop, this effectively limits the loop to 100 iterations at most. If A_SpawnItemEx fails 100 times, the loop will be aborted, spawning nothing. If the loop wasn't aborted, and if A_SpawnItemEx failed infinitely, the engine would freeze. In fact, your current setup makes the loop completely redundant. If A_SpawnItemEx fails once, you don't need to try again, because you know it will never succeed if you retry spawning onto the very same place at the very same time, which is what you are doing here. You'd need something like what Gez suggested instead if you wanted to guarantee that something may get spawned even if the destination was blocked on the first attempt. 0 Share this post Link to post
lwks Posted November 9, 2016 Ok, I know the basics of programming, I know what's happening, but I've never worked with returns, so I didn't know what was that, so it basically ensure that the game doesn't freeze, right? Also, I'm using this now: actor MinionShotgunGuy : ShotgunGuy replaces ShotgunGuy { var int user_spawn; States { Death: SPOS H 5 SPOS I 5 A_Scream SPOS J 5 A_NoBlocking SPOS J 0 { user_spawn = 0; while(!A_SpawnItemEx("ZombieManSpawner",0,0,0,0,0,0) && user_spawn<10) { user_spawn++; } } SPOS K 5 SPOS L -1 Stop XDeath: SPOS H 5 SPOS N 5 A_XScream SPOS O 5 A_NoBlocking SPOS PQRST 5 { user_spawn = 0; while(!A_SpawnItemEx("ZombieManSpawner",0,0,0,0,0,0) && user_spawn<10) { user_spawn++; } } SPOS U -1 Stop } } actor ZombieManSpawner { Radius 20 Height 56 States{ Spawn: TNT1 A 0 TNT1 A 0 A_SpawnItemEx("TeleportFog") TNT1 A 0 A_SpawnItemEx("LookZombieMan",0,0,0,Random(-5, 5),Random(-5, 5),0,SXF_TELEFRAG) TNT1 A 50 TNT1 A 0 A_SpawnItemEx("TeleportFog") TNT1 A 0 A_SpawnItemEx("LookZombieMan",0,0,0,Random(-5, 5),Random(-5, 5),0,SXF_TELEFRAG) Stop } } Telefrag isn't working, wth? Why is that? If the Telefrag don't work I'll need to use the user_spawn 0 Share this post Link to post
Albertoni Posted November 9, 2016 lwks said:actor ZombieManSpawner { Radius 20 Height 56 States{ Spawn: TNT1 A 0 TNT1 A 0 A_SpawnItemEx("TeleportFog") TNT1 A 0 A_SpawnItemEx("LookZombieMan",0,0,0,Random(-5, 5),Random(-5, 5),0,SXF_TELEFRAG) TNT1 A 50 TNT1 A 0 A_SpawnItemEx("TeleportFog") TNT1 A 0 A_SpawnItemEx("LookZombieMan",0,0,0,Random(-5, 5),Random(-5, 5),0,SXF_TELEFRAG) Stop } }Telefrag isn't working, wth? Why is that? If the Telefrag don't work I'll need to use the user_spawn Heh. It's simple, actually. Look at the function header on the wiki:bool A_SpawnItemEx (string type [, float xoffset [, float yoffset [, float zoffset [, float xvelocity [, float yvelocity [, float zvelocity [, float angle [, int flags [, int chance [, int tid ]]]]]]]]])Now let's count. You give the type. You give zeroes for the three offsets. Then you give two randoms for xvelocity and yvelocity and zero for zvelocity. So far so good, good job. Then you say that the angle of the thing should be SXF_TELEFRAG. Hm. That doesn't sound like a good angle to me, no sir. 0 Share this post Link to post
lwks Posted November 9, 2016 LOL, I though I could just throw the SXF anywhere and the code would understant, cause I've actually done this, but with the SXF_NOCHECKPOSITION, and I didn't had any problem, but thanks, gonna try 0 Share this post Link to post
Albertoni Posted November 9, 2016 Maybe in a smarter language you could, but DECORATE and ACS don't hold your hand too much. Also, be sure to check your code with SXF_NOCHECKPOSITION and fix it as well. Right now it might work, but who knows if that won't break things later on. I hope zscript fixes that, making the compiler warn you when you're passing an integer / flag to where you should pass a float. I've spent time figuring out a similar error more than once. >_> 0 Share this post Link to post
lwks Posted November 9, 2016 TY guys, your name will be on the credits, it worked here, and I'll rework the whole mod, then test and release as v1.1, many thanks strangers! You saved my lif...I mean, my mod! xD Edit: Also, the actor that spawns the demons has Height and Radius, but it doesn't Block the player, is it because it doesn't have mass? actor ZombieManSpawner { Radius 20 Height 56 States{ Spawn: TNT1 A 0 TNT1 A 0 A_SpawnItemEx("TeleportFog") TNT1 A 0 A_SpawnItemEx("LookZombieMan",0,0,0,Random(-5, 5),Random(-5, 5),0,0,SXF_TELEFRAG) TNT1 A 50 TNT1 A 0 A_SpawnItemEx("TeleportFog") TNT1 A 0 A_SpawnItemEx("LookZombieMan",0,0,0,Random(-5, 5),Random(-5, 5),0,0,SXF_TELEFRAG) Stop } } 0 Share this post Link to post
Albertoni Posted November 9, 2016 You might have to specifically add the +SOLID flag there (just add "+SOLID" on its own line under height and radius), as I'm pretty sure actors are passable by default. 0 Share this post Link to post
lwks Posted November 9, 2016 Thank you, but that was just out of curiosit, I need them without collision. =) Edit: Ok, just for the record I went to Doom ][ Map 13 and killed some of the Revenants on those Edges and I figured out that the "while (!A_SpawnItemEx)" where causing something very strange, demons killed by the telefrag didn't count as spawned and it seem cause enemies to spawn infinitely, in less than 15 seconds I got like 250 monsters killed, now the whole code follow this structure: actor MinionShotgunGuy : ShotgunGuy replaces ShotgunGuy { States { Death: SPOS H 5 SPOS I 5 A_Scream SPOS J 5 A_NoBlocking SPOS K 5 SPOS K 0 A_SpawnItemEx("ZombieManSpawner",0,0,0,0,0,0) SPOS L -1 Stop XDeath: SPOS H 5 SPOS N 5 A_XScream SPOS O 5 A_NoBlocking SPOS PQRST 5 SPOS T 0 A_SpawnItemEx("ZombieManSpawner",0,0,0,0,0,0) SPOS U -1 Stop } } Yeah, like a normal code... =) Ty anyways 0 Share this post Link to post
Nevander Posted November 11, 2016 Why can't floors/ceilings move if there is no open space between the two sectors to be moved? What I mean is, floor A and B are beside each other (like a joined sector beside a dummy sector) but the two sectors are separated in the vertical void, so the floor of one is all the way above the ceiling of the other. Tested in-game, if they are separated with no open space, the script never runs. With some open space, it works just fine. Is the engine really that stupid that it can't see the floor and ceiling to move to is right beside it? 0 Share this post Link to post
Dragonfly Posted November 11, 2016 Showing your script would help here, and/or a quick screenshot of the area in question in a 3D view would help too. :) 0 Share this post Link to post