EDuke32 Scripting "CON coding help"
#2821 Posted 08 April 2022 - 04:46 PM
#2822 Posted 14 April 2022 - 01:50 PM
Edit: Seems I asked too quickly. I found this: https://github.com/lewster32/webbuild, which has what I would need
This post has been edited by thisbecasper: 14 April 2022 - 02:53 PM
#2823 Posted 18 April 2022 - 05:43 AM
At the moment i'm placing a touchpad right in front of the viewscreen but obviously that creates some sync issues, as I'm relying on the player to hit use immediately upon walking up or the effect is missed.
Cheers!
#2824 Posted 19 April 2022 - 11:48 PM
dandouglas, on 18 April 2022 - 05:43 AM, said:
At the moment i'm placing a touchpad right in front of the viewscreen but obviously that creates some sync issues, as I'm relying on the player to hit use immediately upon walking up or the effect is missed.
Cheers!
Yes, but the first way that comes to mind is a bit convoluted. You would start by tagging the camera sprite with the channel that will activate, but tag it on EXTRA since that isn't used for anything.
If you don't have one already, declare a per actor var for storing channels, and then load that var with the tag.
In your var declarations, add: gamevar mychannel -1 2
Then to save this as a var on the sprite:
eventloadactor CAMERA1 geta[].extra mychannel enda
Then in the player code, you have to detect whether you are viewing from a camera, and if so check to see if the camera is supposed to activate stuff. Activate stuff if applicable, and then reset the var so it doesn't keep activating continuously.
// this part goes in the APLAYER actor ifn player[].newowner -1 { ifn actorvar[player[].newowner].mychannel -1 { getav[player[].newowner].mychannel mychannel operatemasterswitches mychannel operaterespawns mychannel operateactivators mychannel 0 setav[player[].newowner].mychannel -1 set mychannel -1 } }
#2825 Posted 20 April 2022 - 07:29 AM
I've removed the Touchplate, given the Camera sprite an Extra value equivalent to the Lotag of the Activator and added your code, but no sound plays now. I've tried using this new setup with another effect (floor rise) and it doesn't trigger the effect either. Any idea what I could be doing wrong? Thank you!
#2826 Posted 20 April 2022 - 11:26 AM
ifn player[].newowner -1 { al THISACTOR ifn actorvar[player[].newowner].mychannel -1 { getav[player[].newowner].mychannel mychannel al mychannel operatemasterswitches mychannel operaterespawns mychannel operateactivators mychannel 0 setav[player[].newowner].mychannel -1 set mychannel -1 } }
The "al THISACTOR" will add the player's sprite ID to the log. That should completely spam the log when using a camera so if that doesn't happen then you know the code isn't firing at all and the block of code is most likely in the wrong place.
The "al mychannel" only get logged one time if the camera did get set successfully with a channel. You will need to search the log for an instance of "mychannel" after closing the game since it will be hard to see in the other spam. If that does not appear in the log then you know the camera failed to load the channel number into the var. If it does appear then that means that the operate commands using the channel were insufficient to trigger the shooter for some reason.
#2827 Posted 21 April 2022 - 06:21 AM
This is how I've added the code to my GAME.CON - I appreciate that you may not have any more time to look into this.
gamevar mychannel -1 2 eventloadactor CAMERA1 geta[].extra mychannel enda actor APLAYER MAXPLAYERHEALTH PSTAND 0 0 ifn player[].newowner -1 { al THISACTOR ifn actorvar[player[].newowner].mychannel -1 { getav[player[].newowner].mychannel mychannel al mychannel operatemasterswitches mychannel operaterespawns mychannel operateactivators mychannel 0 setav[player[].newowner].mychannel -1 set mychannel -1 } }
#2828 Posted 21 April 2022 - 11:16 AM
https://wiki.eduke32.com/wiki/Newowner
I don't really see how that's possible unless the GAME.CON you are editing isn't even being used in the game.
#2829 Posted 21 April 2022 - 12:45 PM
#2830 Posted 21 April 2022 - 01:01 PM
gamevar mychannel -1 2 eventloadactor CAMERA1 geta[].extra mychannel enda onevent EVENT_GAME ifactor APLAYER ifn player[].newowner -1 { ifn actorvar[player[].newowner].mychannel -1 { getav[player[].newowner].mychannel mychannel al mychannel operatemasterswitches mychannel operaterespawns mychannel operateactivators mychannel 0 setav[player[].newowner].mychannel -1 set mychannel -1 } } endevent
#2831 Posted 21 April 2022 - 01:13 PM
#2832 Posted 21 April 2022 - 03:42 PM
dandouglas, on 21 April 2022 - 01:13 PM, said:
Glad to help. I never would have guessed that whether the struct member is set depends on whether you access it from the actor or in the event. Scripting Duke has a lot of weirds quirks, though, so I shouldn't be that surprised.
#2833 Posted 27 April 2022 - 06:35 AM
After a long period of posing, i have fun with mapster again.
I have some questions regarding code modification to solve some bugs and improve some visual effects:
- how to prevent enemies from killing each other with their shots ? Silly but usefull to avoid this...
- it is possible to create different sort of bullet holes when a player's shot hits differents kinds of wall textures (concrete, metal, wood, etc)?
- a way to determine the id of the wall closest to an actor (like the command "findnearactor" but for walls ?)
Thanks in advance if you have any ideas how to do this, or find pieces of code for this...
#2834 Posted 27 April 2022 - 07:57 AM
zazo, on 27 April 2022 - 06:35 AM, said:
After a long period of posing, i have fun with mapster again.
I have some questions regarding code modification to solve some bugs and improve some visual effects:
- how to prevent enemies from killing each other with their shots ? Silly but usefull to avoid this...
- it is possible to create different sort of bullet holes when a player's shot hits differents kinds of wall textures (concrete, metal, wood, etc)?
- a way to determine the id of the wall closest to an actor (like the command "findnearactor" but for walls ?)
Thanks in advance if you have any ideas how to do this, or find pieces of code for this...
The first of those three is pretty easy to do. The second and third a quite a bit more involved. There just aren't any simple commands for them that do the job.
The friendly fire thing: Every enemy uses the ifhitweapon command. Right before that command in the enemy's code, you can insert a line of code that checks where the damage is coming from and nullifies it if it is coming from another actor that is not the player:
ifn sprite[].htextra -1 ifn sprite[].htowner -1 ifn sprite[].htowner player[].i seta[].htextra -1 ifhitweapon { // ... etc
So you would find each place it says ifhitweapon and insert that line of code above it. In English, what that line of code says is "If you are taking damage and if that damage is coming from a specific sprite and if that sprite is not the player, then negate that damage." This might also prevent them from taking damage from environmental explosions, but hopefully it doesn't do that. I'm hoping that environmental explosions set htowner to -1, in which case they will still take damage from those.
Note that this will not work properly in multiplayer because it only allows damage from the *closest* player. Also, in a more sophisticated mod that has other stuff going on like enemy factions and so on, it should not be used.
#2836 Posted 24 May 2022 - 10:33 AM
Danukem, on 24 November 2021 - 06:30 PM, said:
define NOPALSPRITE #### gamevar tempsprite 0 0 gamevar tempvar 0 0 eventloadactor NOPALSPRITE cstat 32769 headspritesect tempsprite sprite[].sectnum whilevarn tempsprite -1 { geta[tempsprite].htflags tempvar orvar tempvar 64 seta[tempsprite].htflags tempvar nextspritesect tempsprite tempsprite } enda
I think that will work but I'm not entirely sure because the htflags might get overwritten after map load. If that's the case then the code would need to run later.
I guess that what I'm looking for is something with paldata "nofloorpal":
paldata[(pal number)].nofloorpal 1
For example: If sector x have pal 10, then it should'n affect it's containing sprites.
But it seems that paldata is read only, so I can't simply do that:
set paldata[10].nofloorpal 1
As paldata is read only, I guess that the "nofloorpal" flag are probably stored under these guys: LOOKUP.DAT / PALETTE.DAT / TABLES.DAT or it's hardcoded somewhere in eduke32.
#2837 Posted 25 May 2022 - 03:32 PM
Judge me.
#2838 Posted 26 May 2022 - 02:16 AM
#2839 Posted 02 June 2022 - 03:15 AM
P.S. Thanks to Danarama on Discord for the hint.
#2840 Posted 22 June 2022 - 07:47 PM
#2841 Posted 22 June 2022 - 08:13 PM
lllllllllllllll, on 22 June 2022 - 07:47 PM, said:
The recog sounds are a hardcoded feature of the game tied to specific enemies. The only hook into them from the scripting language that I am aware of is EVENT_RECOGSOUND which was added relatively recently and only applies to those old hardcoded cases.
To do what you want on a new useractor you would need to add some special event code that replicates that functionality. What you are trying to do is detect the sprite's .statnum changing from 2 (asleep) to 1 (awake) when its .extra (health) is greater than 0 (because you don't want dead bodies making the sound). And depending on how you had added the sound to the actor code, you might have to remove it from there, since you might get the sound played twice.
#2842 Posted 22 June 2022 - 08:30 PM
gamevar sleeping NO 2 // note that NO and YES are normally defined as 0 and 1 in DEFS.CON onevent EVENT_GAME switch sprite[].picnum case MYENEMY ife sprite[].statnum 2 set sleeping YES break // presumably you will want other cases... endswitch endevent // then elsewhere... useractor enemy MYENEMY MYENEMYHP // lotsa code blah blah blah ife sleeping YES ifg sprite[].extra 0 { sound MYRECOGSOUND set sleeping NO } enda
Note that if an enemy is discovered it may be going from statnum 0 to 1 (not 2 to 1) so it may never have been sleeping; therefore, you would still want to have it making the sound in your ifai 0 block (or ifmove 0, or however you initialize the enemy)
#2843 Posted 23 June 2022 - 11:49 AM
This post has been edited by dandouglas: 23 June 2022 - 11:58 AM
#2844 Posted 23 June 2022 - 12:03 PM
setuserdef[].show_level_text NO
^Execute that line of code before the level's name displays upon map load (for example in EVENT_NEWGAME). If you want it only temporarily disabled then you have to turn it off and on depending on the situation.
#2845 Posted 23 June 2022 - 12:04 PM
useractor notenemy FENCE1 cstat 17 enda
this blocks the player from walking through it, but lets the bullets pass through.
for some strange reason, userart always blocks hitscan and projectiles unless you specifically change the cstat.
This post has been edited by jimbob: 23 June 2022 - 12:07 PM
#2846 Posted 23 June 2022 - 12:32 PM
Danukem, on 23 June 2022 - 12:03 PM, said:
setuserdef[].show_level_text NO
^Execute that line of code before the level's name displays upon map load (for example in EVENT_NEWGAME). If you want it only temporarily disabled then you have to turn it off and on depending on the situation.
Thanks a lot It works perfectly !
This post has been edited by Seb Luca: 23 June 2022 - 12:33 PM
#2847 Posted 23 June 2022 - 01:25 PM
jimbob, on 23 June 2022 - 12:04 PM, said:
useractor notenemy FENCE1 cstat 17 enda
this blocks the player from walking through it, but lets the bullets pass through.
for some strange reason, userart always blocks hitscan and projectiles unless you specifically change the cstat.
This is perfect, thanks so much! I've used cstat 32785 to make invisible sprites
#2848 Posted 23 June 2022 - 09:13 PM
Danukem, on 22 June 2022 - 08:30 PM, said:
gamevar sleeping NO 2 // note that NO and YES are normally defined as 0 and 1 in DEFS.CON onevent EVENT_GAME switch sprite[].picnum case MYENEMY ife sprite[].statnum 2 set sleeping YES break // presumably you will want other cases... endswitch endevent // then elsewhere... useractor enemy MYENEMY MYENEMYHP // lotsa code blah blah blah ife sleeping YES ifg sprite[].extra 0 { sound MYRECOGSOUND set sleeping NO } enda
Note that if an enemy is discovered it may be going from statnum 0 to 1 (not 2 to 1) so it may never have been sleeping; therefore, you would still want to have it making the sound in your ifai 0 block (or ifmove 0, or however you initialize the enemy)
All sprites running the argument every tick sounds intensive yeah.
The idea to check statnum for sleep is perfect.
Since the actor itself can't run code after falling asleep can a spawned sprite reference its parent, and the parent reference a sprite it spawned?
Supposing the useractor spawns an unrendered noclipping sprite which follows duke so it never falls asleep, and that sprite will check the parent's statnum every x count, is the parent be able to kill that sprite (and more importantly would that sprite be able to set a per-actor variable for the parent)?
spriteflags myghost yyyy //unrendered noclipping useractor myactor ifvare temp1 0 //var indicating was asleep { sound myactor_recog spawn myghost setvar temp1 1 } ifdead {myghost}.killit //parent kills spawned sprite enda useractor myghost ifcount 256 { ife {myactor}sprite[].statnum 2 //spawned sprite checks parent's statnum { setvar {myactor}temp1 0 //spawned sprite sets parent's var indicating was sleep killit } else resetcount } enda
#2849 Posted 23 June 2022 - 11:09 PM
lllllllllllllll, on 23 June 2022 - 09:13 PM, said:
There's a simple fix for that though which I didn't include because it will cause problems if you are already using EVENT_GAME. But assuming you are not:
onevent EVENT_GAME switch sprite[].picnum case MYENEMY ife sprite[].statnum 2 set sleeping YES break default geta[].htflags RETURN orvar RETURN 128 seta[].htflags RETURN break endswitch endevent
So now only the cases you want will check statnum to set sleeping, and all other sprites in the game will be exluded from any processing in EVENT_GAME after the initial check. https://wiki.eduke32.com/wiki/Htflags
Spawning an additional sprite to check on the first sprite is possible, although it comes with its own baggage. For example, some maps get close to the sprite limit so spawning lots of extra sprites should be discouraged.
But it occurs to me that there may be a better method than either of those. As a sprite gets closer to sleeping, its .httimetosleep member gets incremented. I have never researched the precise behavior of that counter, but what if the counter only gets lower when it is reset upon wakeup? If that's the case, then you could simply have the actor make the RECOG sound whenever httimetosleep is < what it was last tic:
ifl sprite[].httimetosleep sleeptime sound MYRECOG geta[].httimetosleep sleeptime
#2850 Posted 24 June 2022 - 10:31 AM
Danukem, on 23 June 2022 - 11:09 PM, said:
ifl sprite[].httimetosleep sleeptime sound MYRECOG geta[].httimetosleep sleeptime
As you thought it only lowers after the enemy is awakened again, it gives strange results though.
First I used
useractor myactor ife sprite[].httimetosleep 0 sound MYRECOG enda
This resulted in sleeping and reawakening enemies playing their RECOG properly, but enemies spawned via respawn didn't play the sound.
That made me think the respawning enemies have a higher initial value for httimetosleep, so I combined the above with the previous:
useractor myactor ifvare temp1 0 { sound MYRECOG setvar temp1 1 } else ife sprite[].httimetosleep 0 sound MYRECOG enda
This resulted in all forms of the enemy playing their sound after a 4 tick delay.
I figured that httimetosleep was somehow still being calculated on the first tick:
useractor myactor ifvare temp1 1 { ife sprite[].httimetosleep 0 sound MYRECOG } else { sound MYRECOG setvar temp1 1 } enda
but this results in even weirder behavior. All forms of enemies are playing the sound after ~4 tick delay but it doesn't always play.
It makes it seem like httimetosleep is starting with negative values and the times it doesn't play are where the increment skips 0.
But even in that case I don't understand why the bit following else is not working whenever ife sprite[].httimetosleep is used.
After messing around with it more I ended up with
useractor myenemy ifvare temp1 0 { sound MYRECOG setvar temp1 1 } else ifvare temp1 1 { ifcount 64 setvar temp1 2 } else ife sprite[].httimetosleep 0 sound MYRECOG state actorcode enda
and, as far as I've tested, this works
Thankfully when they fall asleep httimetosleep gets set to exactly 0