
EDuke32 Scripting "CON coding help"
#3572 Posted 03 November 2024 - 07:10 PM
#3573 Posted 04 November 2024 - 06:27 AM
Reaper_Man, on 03 November 2024 - 07:10 PM, said:
Ok I’ll check that out. Like I said it’s not a huge deal since the enemies that will be painted with these target icons will more than likely be on the floor and close by in the next room anyways. So no big deal. You’ve provided lots of help regardless. Thanks again.
This post has been edited by VGames: 04 November 2024 - 06:28 AM
#3574 Posted 13 November 2024 - 09:44 AM
-Edit the muzzle flash of the chaingun? I see there's a sprite for the chaingun muzzle flash, but it seems to be rendered three times, roughly around where each of the chaingun's barrels are. I've seen some classic total conversions just blank out the sprites for this flash, but I would like to keep it, just color it blue and only have it shown once about where the plasma rifle's barrel is.
-Animate the chaingun ammo pickup? I'm trying to make a mod that doesn't interfere with anything already in place (so you could still play the original levels, just with the new player character and weapons). The default chaingun ammo sprite isn't animated, but the plasma rifle battery pickup is, so I basically wanted to put in a simple CON script that would have the battery pickup (the first frame of which would replace the original box of ammo) jump to the new ART tiles for a couple frames and then come back to the original one. That way the pickup would be animated but all the original chaingun ammo pickups in the original maps don't need new sprites set. I know there's a way to set animations in the ARTs themselves, but those assume the frames are all right next to each other.
#3575 Posted 13 November 2024 - 02:44 PM
Certainly there are a lot of things that are impossible to do in EDuke32, but there's also a huge amount of possibilities. In general I don't think its very useful to ask whether something is possible, because then some smartass such as myself might simply say "yes" and that doesn't put you any farther forward. What you want to know is expert opinions on the best way to accomplish your goals.
#3576 Posted 27 November 2024 - 10:33 PM
#3577 Posted 27 November 2024 - 11:32 PM
#3578 Posted 28 November 2024 - 03:35 PM
Danukem, on 27 November 2024 - 11:32 PM, said:
This is too meh for me... I just want new variations of buttons in the game and keep the existing ones. Some mods did that, but I couldn't replicate that.
I got codes from Memories mod which appears to have at least to funcional textures for a button... One off and another on, in a way they could behave like any other buttons in the game.
These are the codes I found so far related to 2 of the textures of the mod:
//////////MEMOGAME.CON
define BADSWITCH 3935
//////////MEMEXTRA.CON
action ABADSWITCH1 0 0 0 0 2 action ABADSWITCH2 1 0 0 0 2 actor BADSWITCH sleeptime -1 ifaction 0 action ABADSWITCH1 ifaction ABADSWITCH1 { ifcansee ifhitspace ifpdistg 1500 setvar PRESS_VAR 2 ifpdistl 1500 ifvare PRESS_VAR 0 ifcansee ifp pfacing ifhitspace { sound NEWBUTTON operateactivators 9892 myconnectindex setvar PRESS_VAR 2 action ABADSWITCH2 } } enda
The textures for the button are 3935 (off) and 3936 (on).
I tried to make a new button following this pattern, but failed, like this:
action ALAMEBUTTON1 0 0 0 0 2 action ALAMEBUTTON2 1 0 0 0 2 actor LAMEBUTTON sleeptime -1 ifaction 0 action ALAMEBUTTON1 ifaction ALAMEBUTTON1 { ifcansee ifhitspace ifpdistg 1500 setvar PRESS_VAR 2 ifpdistl 1500 ifvare PRESS_VAR 0 ifcansee ifp pfacing ifhitspace { sound SWITCH_ON operateactivators 9892 myconnectindex setvar PRESS_VAR 2 action ABADSWITCH2 } } enda
I also have this code, but the button fails to interact with the lotag activator (I put 100 in the map), and doesn't work either, same for the code above:
//LAMEBUTTON define LAMEBUTTON_STATE_OFF 0 define LAMEBUTTON_STATE_ON 1 define LAMEBUTTON_STATE_LOCKED 2 gamevar LAMEBUTTON_STATE 0 // Estado principal do LAMEBUTTON Toggle state LAMEBUTTON_TOGGLE ifvare LAMEBUTTON_STATE LAMEBUTTON_STATE_OFF setvar LAMEBUTTON_STATE LAMEBUTTON_STATE_ON cstat 1 return setvar LAMEBUTTON_STATE LAMEBUTTON_STATE_OFF cstat 257 ends // Evento de uso do LAMEBUTTON onevent EVENT_USE ifspritepal LAMEBUTTON_STATE_LOCKED quote 1 return state LAMEBUTTON_TOGGLE endevent
I made a definition for the tile LAMEBUTTON in DEFS.CON.
Also, I tried to add other colors to ACCESSCARD and ACCESSSWITCH1 and ACCESSSWITCH2, but I have no clue how to do that.
So I tried to add a new keycard (ACCESSCARD2) and a new switch (ACCESSSWITCH3) as actors, like what was done in Memories, but I also failed.
Here are the codes in Memories mod I found so far related to accesscards and accessswitches:
actor ACCESSCARD ifspawnedby APLAYER { spritepal 21 getplayer[THISACTOR].posx TEMP setactor[THISACTOR].x TEMP getplayer[THISACTOR].posy TEMP setactor[THISACTOR].y TEMP getplayer[THISACTOR].cursectnum TEMP setactor[THISACTOR].sectnum TEMP getplayer[THISACTOR].posz TEMP setactor[THISACTOR].z TEMP } ifspawnedby SPAWNER_SPRITE cstat 0 fall ifspawnedby ITEMBAG spritepal 23 ifspawnedby SPAWNER_SPRITE spritepal 21 ifmove RESPAWN_ACTOR_FLAG state respawnit else ifp pshrunk nullop else ifp palive ifpdistl RETRIEVEDISTANCE ifcount 6 ifcanseetarget { ifpinventory GET_ACCESS 0 break addinventory GET_ACCESS 1 quote 43 ifspritepal 23 ifvare FORGET 1 setvar SHOWYOURSELF 1 state getcode } enda actor NEWACCESSCARD fall ifp palive ifpdistl RETRIEVEDISTANCE ifcount 6 ifcanseetarget { setvar GHOSTCARD 1 quote 177 state getcode } enda actor NEWACCESSCARD2 fall ifaction 0 { cstat 32768 ifvarg NEWGOD 0 action ZERO } ifaction ZERO { cstat 0 ifp palive ifpdistl RETRIEVEDISTANCE ifcount 6 ifcanseetarget { stopsound WAR_AMBIENCE1 stopsound WAR_AMBIENCE2 stopsound WAR_AMBIENCE3 stopsound WAR_AMBIENCE4 setvar MOLDYCARD 1 setvar NEWGOD 2 quote 250 setvar NEWGOD 4 state getcode } } enda actor NEWACCESSCARD3 // fall ifaction 0 ifp palive ifpdistl RETRIEVEDISTANCE ifcount 6 ifcanseetarget { setvar BLOODCARD 1 operateactivators 1027 myconnectindex quote 295 palfrom 18 63 cstat 32768 globalsound DUKE_GET action ZERO } ifaction ZERO ifactioncount 35 { setvar OPERATE 182 killit } enda action ANEWACCESSSWITCH1 0 0 0 0 2 action ANEWACCESSSWITCH2 1 0 0 0 2 actor NEWACCESSSWITCH sleeptime -1 ifaction 0 action ANEWACCESSSWITCH1 ifaction ANEWACCESSSWITCH1 { ifcansee ifhitspace ifpdistg 1500 setvar PRESS_VAR 2 ifpdistl 1500 ifvare PRESS_VAR 0 ifcansee ifp pfacing ifhitspace { ifvare GHOSTCARD 0 { quote 178 setvar PRESS_VAR 2 } else ifvare GHOSTCARD 1 { operateactivators 118 myconnectindex setvar PRESS_VAR 2 setvar GHOSTCARD 0 sound MONITOR_ACTIVE2 lockplayer 20 tip action ANEWACCESSSWITCH2 } } } ifaction ANEWACCESSSWITCH2 { ifrnd 128 setactor[THISACTOR].shade 15 else setactor[THISACTOR].shade 12 } enda action ANEWACCESSSWITCH20 0 0 0 0 2 action ANEWACCESSSWITCH21 0 0 0 0 2 action ANEWACCESSSWITCH22 0 0 0 0 2 actor NEWACCESSSWITCH2 sleeptime -1 ifaction 0 { cstat 32768 ifvare OPERATE 832 action ANEWACCESSSWITCH20 } ifaction ANEWACCESSSWITCH20 { cstat 80 ifcansee ifpdistl 1700 { setvar OPERATE 833 action ANEWACCESSSWITCH21 } } ifaction ANEWACCESSSWITCH21 { cstat 80 ifcansee ifhitspace ifpdistg 1500 setvar PRESS_VAR 2 ifpdistl 1500 ifvare PRESS_VAR 0 ifcansee ifp pfacing ifhitspace { ifvare MOLDYCARD 0 { quote 249 setvar PRESS_VAR 2 } else ifvare MOLDYCARD 1 { tip operateactivators 2265 myconnectindex setvar PRESS_VAR 2 setvar MOLDYCARD 2 sound MONITOR_ACTIVE2 lockplayer 20 action ANEWACCESSSWITCH22 } } } ifaction ANEWACCESSSWITCH22 { ifrnd 128 setactor[THISACTOR].shade 15 else setactor[THISACTOR].shade 12 ifactioncount 4 cstat 82 ifactioncount 8 cstat 594 ifactioncount 12 killit } enda actor NEWACCESSSWITCH3 sleeptime -1 ifaction 0 ifpdistl 4000 action ANEWACCESSSWITCH1 ifaction ANEWACCESSSWITCH1 { ifpdistg 4000 action 0 ifcansee ifhitspace ifpdistg 1500 setvar PRESS_VAR 2 ifpdistl 1500 ifvare PRESS_VAR 0 ifcansee ifp pfacing ifhitspace { ifvare BLOODCARD 0 { quote 296 setvar PRESS_VAR 2 } else ifvare BLOODCARD 1 { operateactivators 838 myconnectindex setvar PRESS_VAR 2 setvar BLOODCARD 0 tip globalsound BLOODSWITCH lockplayer 20 palfrom 24 63 action ANEWACCESSSWITCH2 } } } enda
I tried to replicate that in the extra tiles I made, adapting to the name, but I failed. Is there something missing here? I made definitions for the tiles ACCESSCARD2 and ACCESSSWITCH3 in DEFS.CON.
Here's an example:
actor ACCESSCARD2 fall ifp palive ifpdistl RETRIEVEDISTANCE ifcount 6 ifcanseetarget { setvar ACCESSCARD2 1 quote 1010 state getcode } enda action AACCESSSWITCH3 0 0 0 0 2 actor ACCESSSWITCH3 sleeptime -1 ifaction 0 { cstat 32768 ifvare OPERATE 832 action ACCESSSWITCH3 } }
Or there's something missing here, or this is more complicated than I thought.
There's Nuclear Showdown mod, but that mod is old and based on an older version of Eduke32, so the codes are not more compatible.
Note: I couldn't upload the TILES.ART from Memories mod because they are too big!
I'm just trying to "expand" the game.

#3579 Posted 28 November 2024 - 04:41 PM
Also taking code from Memories is probably a bad idea because so much of that mod is misdirection. None of those buttons are doing button-y things, and why they aren't (and what they ARE doing) is so specific to that mod.
In the most simple terms, "a switch" just triggers Activators and Masterswitches via operateactivators and operatemasterswitches. Maybe operatesectors too, I'd have to go look. So if you just want a switch to do switch things, that's what "doing switch things" means. That may not be what you need or want them to do though, because they also technically do a lot of other work like triggering game quotes and automatically playing sounds.
#3580 Posted 28 November 2024 - 05:09 PM
Quote
Also taking code from Memories is probably a bad idea because so much of that mod is misdirection. None of those buttons are doing button-y things, and why they aren't (and what they ARE doing) is so specific to that mod.
In the most simple terms, "a switch" just triggers Activators and Masterswitches via operateactivators and operatemasterswitches. Maybe operatesectors too, I'd have to go look. So if you just want a switch to do switch things, that's what "doing switch things" means. That may not be what you need or want them to do though, because they also technically do a lot of other work like triggering game quotes and automatically playing sounds.
Ok, thank's for the hint. I'll try to use operateactivators, operatemasterswitches and operatesectors. Maybe to create a switch you have to make a very specific script, but I still can't fugure out exactly, but I'll try.
I'm also trying to make additional keycards to the game, by creating new items, but that seems even more complex.
I saw somewhere that in order to add new possible colors for existing keycards and accessswitches, you have to change the source code. There was a mod that did add new colors for that, but I don't know if it was by .CON or by changing the source code.
My idea is that if a mod made something using .CON only and that worked, then it's possible to implement in the game in an individual way for other purposes.
For example, if I want to make an addon for a mod for personal use (what i'm doing right now) or create a new mod, then it's possible to somehow replicate things from other mods. Modders usually do that.
#3581 Posted 28 November 2024 - 09:05 PM
#3582 Posted 01 December 2024 - 06:40 PM
/////////////////NEW SWITCHES gamevar LOTAGSAVED 0 2 gamevar HITAGSAVED 0 2 action ONE 1 state CUSTOMSWITCH ifpdistl 1548 ifp palive ifp pfacing ifcansee ifhitspace ifcount 13 { sound SWITCH_ON ifvare HITAGSAVED 0 { ifactor LAMEBUTTON sound SWITCH_ON} else { soundvar HITAGSAVED } ifaction 0 { action ONE } else ifaction ONE { action 0 } operateactivators LOTAGSAVED THISACTOR operaterespawns LOTAGSAVED operatemasterswitches LOTAGSAVED resetcount } else ifactor LAMEBUTTON ifhitweapon ifcount 13 { strength 1 cstator 256 ifvare HITAGSAVED 0 { ifactor LAMEBUTTON sound SWITCH_ON } else { soundvar HITAGSAVED } ifaction 0 { action ONE } else ifaction ONE { action 0 } operateactivators LOTAGSAVED THISACTOR operaterespawns LOTAGSAVED operatemasterswitches LOTAGSAVED resetcount } ends useractor notenemy LAMEBUTTON cstator 256 state CUSTOMSWITCH enda eventloadactor 10445 { getactor[THISACTOR].hitag HITAGSAVED getactor[THISACTOR].lotag LOTAGSAVED setactor[THISACTOR].hitag 0 setactor[THISACTOR].lotag 0 } enda
With this, I can now use it as a base to create all the other custom buttons in my maps. It was based on a mod's script. It took me several hours to make a functional script, but here it is, in case anyone wants to use this code as a base to create a functional button, related to the use of lotags and hitags. It is not enough to just create an actor, there has to be something that allows this actor to interact with sector activation functions. I took advantage of some tips about operateactivators, operaterespawns and operatemasterswitches and then I ended up discovering them in the mod, and then I incorporated them into the script and bingo, it finally worked. The next step now is to add new custom access cards, in addition to custom access switches, something I've already done and it worked, and which I'll show you next.
/////////////////NEW KEYCARD gamevar ACCESSKEY2 0 1 gamevar TEMP 0 2 gamevar TEMP2 0 2 gamevar TEMP3 0 2 gamevar TEMP4 0 2 gamevar TEMP5 0 2 gamevar TEMP6 0 2 gamevar TEMP7 0 2 gamevar LOTAGSAVED 0 2 gamevar HITAGSAVED 0 2 gamevar CUSTOMKEYCARDPOS 0 gamevar CKEYCARDPAL 0 0 gamevar CKEYCARDTILE 0 0 gamevar ACCESSKEY2 0 1 gamevar ZERO 0 2 gamevar ANIMATIONACTIVE 0 gamevar ANIMTIMER 0 define DOUBLESIZE 131072 define NORMALSIZE 65536 define HALFSIZE 32768 define QUARTERSIZE 16384 define ANIMDELAY 16 define EVENT_GETACCESSCARD 100 define EVENT_USESWITCH 13 define EVENT_DISPLAYCROSSHAIR 9 define EVENT_DISPLAYROOMS 6 define EVENT_ACTIVATESWITCH 8 action ONE 1 action LOCKED 0 action UNLOCKING 0 action UNLOCKED 1 state DISPLAYGREYKEY rotatesprite 261 31 QUARTERSIZE 0 15175 0 4 545 ZERO ZERO xdim ydim rotatesprite 260 30 QUARTERSIZE 0 15175 0 12 512 ZERO ZERO xdim ydim ends state DISPLAYGREENKEY rotatesprite 251 21 QUARTERSIZE 0 15175 0 4 545 ZERO ZERO xdim ydim rotatesprite 250 20 QUARTERSIZE 0 15175 0 11 512 ZERO ZERO xdim ydim ends state DISPLAYBROWNKEY rotatesprite 241 11 QUARTERSIZE 0 15175 0 4 545 ZERO ZERO xdim ydim rotatesprite 240 10 QUARTERSIZE 0 15175 0 15 512 ZERO ZERO xdim ydim ends eventloadactor ACCESSCARD2 setactor[THISACTOR].xrepeat 28 setactor[THISACTOR].yrepeat 28 enda useractor notenemy ACCESSCARD2 ifp pshrunk nullop else ifp palive ifpdistl RETRIEVEDISTANCE ifcount 6 ifcanseetarget { ifspritepal 12 { ifvarand ACCESSKEY2 1 { break } else { addvar ACCESSKEY2 1 quote 1013 // "GREY ACCESS CARD ACQUIRED" } } else ifspritepal 11 { ifvarand ACCESSKEY2 2 { break } else { addvar ACCESSKEY2 2 quote 1014 // "GREEN ACCESS CARD ACQUIRED" } } else ifspritepal 15 { ifvarand ACCESSKEY2 4 { break } else { addvar ACCESSKEY2 4 quote 1015 // "BROWN ACCESS CARD ACQUIRED" } } globalsound DUKE_GET quote 43 palfrom 16 0 32 killit } enda onevent EVENT_DISPLAYCROSSHAIR ifvarand ACCESSKEY2 1 { state DISPLAYGREYKEY } ifvarand ACCESSKEY2 2 { state DISPLAYGREENKEY } ifvarand ACCESSKEY2 4 { state DISPLAYBROWNKEY } endevent /////////////////NEW ACCESSSWITCH eventloadactor ACCESSSWITCH3 { espawn 2568 getactor[THISACTOR].pal TEMP setactor[RETURN].pal TEMP getactor[THISACTOR].hitag HITAGSAVED getactor[THISACTOR].lotag LOTAGSAVED setactor[THISACTOR].hitag 0 setactor[THISACTOR].lotag 0 } enda state checkcounterpart2 setvar TEMP 0 whilevarn TEMP 16384 { getactor[TEMP].statnum TEMP4 ifvarn TEMP4 1024 { getactor[TEMP].picnum TEMP2 ifvare TEMP2 ACCESSSWITCH3 { getactorvar[TEMP].LOTAGSAVED TEMP3 ifvarvare LOTAGSAVED TEMP3 { setactor[TEMP].picnum 15177 } } } addvar TEMP 1 } ends state CUSTOMACCESSSWITCH ifaction 0 { action LOCKED } ifpdistl 1024 ifhitspace ifaction LOCKED { getactor[THISACTOR].pal TEMP ifvare TEMP 11 { ifvarand ACCESSKEY2 2 { quote 1016 // "GREEN ACCESS CARD GRANTED" state checkcounterpart2 sound SWITCH_ON setvar CUSTOMKEYCARDPOS 1 operateactivators LOTAGSAVED THISACTOR operaterespawns LOTAGSAVED operatemasterswitches LOTAGSAVED action UNLOCKED subvar ACCESSKEY2 2 } else { quote 1013 } // "GREEN ACCESS CARD REQUIRED" } else ifvare TEMP 12 { ifvarand ACCESSKEY2 1 { quote 1017 // "GREY ACCESS CARD GRANTED" state checkcounterpart2 sound SWITCH_ON setvar CUSTOMKEYCARDPOS 1 operateactivators LOTAGSAVED THISACTOR operaterespawns LOTAGSAVED operatemasterswitches LOTAGSAVED action UNLOCKED subvar ACCESSKEY2 1 } else { quote 1014 } // "GREY ACCESS CARD REQUIRED" } else ifvare TEMP 15 { ifvarand ACCESSKEY2 4 { quote 1018 // "BROWN ACCESS CARD GRANTED" state checkcounterpart2 sound SWITCH_ON setvar CUSTOMKEYCARDPOS 1 operateactivators LOTAGSAVED THISACTOR operaterespawns LOTAGSAVED operatemasterswitches LOTAGSAVED action UNLOCKED subvar ACCESSKEY2 4 } else { quote 1015 } // "BROWN ACCESS CARD REQUIRED" } } ends useractor notenemy ACCESSSWITCH3 state CUSTOMACCESSSWITCH enda
Here is the code I used to make functional cards and switches. And not only that, but I also used different palettes, for green (11), gray (12) and brown (15). I got this code from Nuclear Showndown, so I already had the basis, but I still lacked knowledge about the codes and parameters. In this case, I had to do a lot of trial and error with the help of artificial intelligence (Claude 3.5 Sonnet and GPT 4), because it was too difficult for me to understand how to assemble the code alone. On several occasions, the AI ​​made mistakes, but on other occasions I was the one who made the mistakes while assembling the script. This way, I ended up learning better how to create custom cards as well as customizable card switches. Because of so much trial and error and code research, I ended up getting a better understanding of the syntax and how scripts should be constructed, although I'm still not an expert in this. After all, game programming has become a new thing for me recently.
Also, based on Nuclear Showndown, I managed to make the icons of the cards I pick up appear on the HUD, more or less like they do in the mod. But I only did it for the extra colors, and not for the ones that are already in the game originally.
For those who need a script to create new cards and switches, here it is for newbies in .CON programming who need this. One day, when I've already managed to create several things using codes, maybe I'll create a topic just for this.
Ok, now that the cards and switches are working normally on my map, as well as the icons of the cards acquired in the HUD, all that's left is to deal with the animation, the one when the player activates a switch and Duke Nukem's hand appears holding a card and then the hand without the card. I spent over a day trying to deal with this, with partial success.
/////////////////NEW CARD ANIMATIONS onevent EVENT_DISPLAYCROSSHAIR ifvarn CUSTOMKEYCARDPOS 0 { addvar ANIMTIMER 256 ifvarn ANIMTIMER 512 { setvar ANIMTIMER 0 switch CUSTOMKEYCARDPOS case 0: break case 1: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 2: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 3: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 4: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 5: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 6: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 7: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 8: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 9: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 10: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 11: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 12: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 13: rotatesprite 160 134 NORMALSIZE 0 2563 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 14: rotatesprite 160 134 NORMALSIZE 0 2563 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 15: rotatesprite 160 134 NORMALSIZE 0 2563 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 16: rotatesprite 160 134 NORMALSIZE 0 2563 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 17: rotatesprite 120 134 NORMALSIZE 0 2564 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 18: rotatesprite 120 134 NORMALSIZE 0 2564 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 19: rotatesprite 120 134 NORMALSIZE 0 2564 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 20: rotatesprite 120 134 NORMALSIZE 0 2564 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 21: rotatesprite 80 134 NORMALSIZE 0 2565 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 22: rotatesprite 80 134 NORMALSIZE 0 2565 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 23: rotatesprite 80 134 NORMALSIZE 0 2565 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 24: rotatesprite 80 134 NORMALSIZE 0 2565 0 0 0 0 0 xdim ydim setvar CUSTOMKEYCARDPOS 0 setvar ANIMATIONACTIVE 0 break endswitch } } endevent onevent EVENT_ACTIVATESWITCH ifvare ANIMATIONACTIVE 0 { setvar CUSTOMKEYCARDPOS 1 setvar ANIMATIONACTIVE 1 } endevent
The animation involves several repeated lines, since if I put only one animation line for each texture and color, it will appear very fast in the animation, while the original in the game is slower and smoother between animations.
Now this is the part where I'm having trouble. I'm starting to understand this rotatesprite thing and its parameters, after countless trials and errors using flags. HANDHOLDINGACCESS (texture 2568) was more complicated, because the original texture is in a horizontally inverted position in relation to what appears in the animation, so I had to use a flag and change the sprite angle value. Then I was able to straighten it, like in the game's animation. Then, since there are other textures in the animation in the game, I also had to use those (textures 2563, 2564 and 2565) for the texture of the hand without the card. Since in this case the textures are already in the right position in relation to the animation in the game, I didn't need to change the angle. If you test the animation script, you'll notice that the animation is very similar to the original in the game. There's just one little problem. I've tried several times to use flags to put the texture behind the status bar, but I can't do it through flags, not even by setting the specific pure value for it.
I'm also not sure if "setvar CUSTOMKEYCARDPOS 1" is correct in the switch and animation script so that the animation responds according to the specific color for accesscard and acessswitch.
And this is where I need help. Then all that's left is to establish a set of independent animations for each card color (green, gray and brown).
If I can do this or if someone can help me with this, I'll have achieved everything I need regarding cards, switches and card animations.
#3583 Posted 01 December 2024 - 07:30 PM
#3584 Posted 02 December 2024 - 07:54 AM
I'm trying here about the pal thing, but the layer thing I just don't have a hint on how to solve that.
This post has been edited by eniojr: 02 December 2024 - 07:54 AM
#3585 Posted 02 December 2024 - 08:55 AM
onevent EVENT_DISPLAYCROSSHAIR ifvarn CUSTOMKEYCARDPOS 0 { addvar ANIMTIMER 256 ifvarn ANIMTIMER 512 { setvar ANIMTIMER 0 switch CUSTOMKEYCARDPOS case 0: break case 1: rotatesprite 160 134 NORMALSIZE 1024 HANDHOLDINGACCESS 0 0 260 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 2: rotatesprite 160 134 NORMALSIZE 0 2563 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 3: rotatesprite 120 134 NORMALSIZE 0 2564 0 0 0 0 0 xdim ydim addvar CUSTOMKEYCARDPOS 1 break case 4: rotatesprite 80 134 NORMALSIZE 0 2565 0 0 0 0 0 xdim ydim setvar CUSTOMKEYCARDPOS 0 setvar ANIMATIONACTIVE 0 break endswitch } } endevent onevent EVENT_ACTIVATESWITCH ifvare ANIMATIONACTIVE 0 { setvar CUSTOMKEYCARDPOS 1 setvar ANIMATIONACTIVE 1 } endevent
#3586 Posted 02 December 2024 - 10:14 AM
eniojr, on 02 December 2024 - 07:54 AM, said:
I'm trying here about the pal thing, but the layer thing I just don't have a hint on how to solve that.
Try doing the drawing in EVENT_DISPLAYWEAPON. Also I presume you already have a way of making sure the weapon isn't being drawn at the same time.
#3587 Posted 02 December 2024 - 12:07 PM
#3588 Posted 02 December 2024 - 12:25 PM
#3589 Posted 05 December 2024 - 06:34 PM
#3590 Posted 06 December 2024 - 01:57 PM
Two ways really: Check for the value of userdef[].return 1 and if it's anything other than -1, that means it was radius damage.
Or, check sprite[RETURN].htpicnum for the specific weapon name/tile ID for what you want to match against. This would basically be an equivalent of "ifwasweapon".
The first method is probably more reliable, but the second method would let you check specifically for RADIUSDAMAGE as a defined attack, rather than all types of radius damage.
This post has been edited by Reaper_Man: 06 December 2024 - 01:58 PM
#3591 Posted 06 December 2024 - 02:05 PM
#3592 Posted 06 December 2024 - 02:50 PM
#3593 Posted 10 December 2024 - 11:16 PM
Here's the code, if you want to use for yourself:
gamevar ACCESSKEY2 0 1 gamevar CUSTOMKEYCARDPOS 0 0 gamevar KEYCARD_CURRENT_PAL 0 0 gamevar CKEYCARDPAL 0 0 gamevar CKEYCARDTILE 0 0 gamevar KEYCARD_TEMP 0 2 gamevar KEYCARD_TEMP2 0 2 gamevar KEYCARD_TEMP3 0 2 gamevar KEYCARD_TEMP4 0 2 gamevar KEYCARD_TEMP7 0 0 define DOUBLESIZE 131072 define NORMALSIZE 65536 define HALFSIZE 32768 define QUARTERSIZE 16384 action LOCKED 0 action UNLOCKING 0 action UNLOCKED 1 eventloadactor ACCESSCARD2 setactor[THISACTOR].xrepeat 28 setactor[THISACTOR].yrepeat 28 enda useractor notenemy ACCESSCARD2 ifp pshrunk nullop else ifp palive ifpdistl RETRIEVEDISTANCE ifcount 6 ifcanseetarget { // Verifica cor do cartão e adiciona ao inventário ifspritepal 12 { ifvarand ACCESSKEY2 1 { break } else { addvar ACCESSKEY2 1 setvar KEYCARD_TEMP7 30 globalsound DUKE_GET quote 43 palfrom 16 0 32 killit break } } ifspritepal 11 { ifvarand ACCESSKEY2 2 { break } else { addvar ACCESSKEY2 2 setvar KEYCARD_TEMP7 30 globalsound DUKE_GET quote 43 palfrom 16 0 32 killit break } } ifspritepal 15 { ifvarand ACCESSKEY2 4 { break } else { addvar ACCESSKEY2 4 setvar KEYCARD_TEMP7 30 globalsound DUKE_GET quote 43 palfrom 16 0 32 killit break } } ifspritepal 10 { ifvarand ACCESSKEY2 8 { break } else { addvar ACCESSKEY2 8 setvar KEYCARD_TEMP7 30 globalsound DUKE_GET quote 43 palfrom 16 0 32 killit break } } ifspritepal 13 { ifvarand ACCESSKEY2 16 { break } else { addvar ACCESSKEY2 16 setvar KEYCARD_TEMP7 30 globalsound DUKE_GET quote 43 palfrom 16 0 32 killit break } } ifspritepal 14 { ifvarand ACCESSKEY2 32 { break } else { addvar ACCESSKEY2 32 setvar KEYCARD_TEMP7 30 globalsound DUKE_GET quote 43 palfrom 16 0 32 killit break } } ifspritepal 16 { ifvarand ACCESSKEY2 64 { break } else { addvar ACCESSKEY2 64 setvar KEYCARD_TEMP7 30 globalsound DUKE_GET quote 43 palfrom 16 0 32 killit break } } ifspritepal 30 { ifvarand ACCESSKEY2 128 { break } else { addvar ACCESSKEY2 128 setvar KEYCARD_TEMP7 30 globalsound DUKE_GET quote 43 palfrom 16 0 32 killit break } } } enda eventloadactor ACCESSSWITCH3 { getactor[THISACTOR].pal KEYCARD_TEMP setactor[RETURN].pal KEYCARD_TEMP getactor[THISACTOR].hitag HITAGSAVED getactor[THISACTOR].lotag LOTAGSAVED setactor[THISACTOR].hitag 0 setactor[THISACTOR].lotag 0 setactor[THISACTOR].cstat 17 setactor[THISACTOR].clipdist 64 } enda state checkcounterpart2 setvar KEYCARD_TEMP 0 whilevarn KEYCARD_TEMP 16384 { getactor[KEYCARD_TEMP].statnum KEYCARD_TEMP4 ifvarn KEYCARD_TEMP4 1024 { getactor[KEYCARD_TEMP].picnum KEYCARD_TEMP2 ifvare KEYCARD_TEMP2 ACCESSSWITCH3 { getactorvar[KEYCARD_TEMP].LOTAGSAVED KEYCARD_TEMP3 ifvarvare LOTAGSAVED KEYCARD_TEMP3 { setactor[KEYCARD_TEMP].picnum 15177 } } } addvar KEYCARD_TEMP 1 } ends state CUSTOMACCESSSWITCH ifaction 0 { action LOCKED } ifpdistl 1024 ifhitspace ifaction LOCKED { ifvarg KEYCARD_TEMP7 0 { break } getactor[THISACTOR].hitag KEYCARD_TEMP ifvare KEYCARD_TEMP 0 { setvar KEYCARD_TEMP7 1 } ifvarand ACCESSKEY2 1 nullop else ifvarand ACCESSKEY2 2 nullop else ifvarand ACCESSKEY2 4 nullop else ifvarand ACCESSKEY2 8 nullop else ifvarand ACCESSKEY2 16 nullop else ifvarand ACCESSKEY2 32 nullop else ifvarand ACCESSKEY2 64 nullop else ifvarand ACCESSKEY2 128 nullop else break ifspritepal 12 { ifvarand ACCESSKEY2 1 { setvar CKEYCARDTILE 2568 setvar CKEYCARDPAL 12 setvar CUSTOMKEYCARDPOS 21 setvar KEYCARD_TEMP2 1 action UNLOCKING ifrnd 128 { globalsound OPEN_SESAME } else { ifrnd 128 { globalsound LETS_SEE } else { globalsound GETTIN_SOMEWHRE } } } else { globalsound NO_KEY1 quote 1014 } } ifspritepal 11 { ifvarand ACCESSKEY2 2 { setvar CKEYCARDTILE 2568 setvar CKEYCARDPAL 11 setvar CUSTOMKEYCARDPOS 21 setvar KEYCARD_TEMP2 1 action UNLOCKING ifrnd 128 { globalsound OPEN_SESAME } else { ifrnd 128 { globalsound LETS_SEE } else { globalsound GETTIN_SOMEWHRE } } } else { globalsound NO_KEY2 quote 1013 } } ifspritepal 15 { ifvarand ACCESSKEY2 4 { setvar CKEYCARDTILE 2568 setvar CKEYCARDPAL 15 setvar CUSTOMKEYCARDPOS 21 setvar KEYCARD_TEMP2 1 action UNLOCKING ifrnd 128 { globalsound OPEN_SESAME } else { ifrnd 128 { globalsound LETS_SEE } else { globalsound GETTIN_SOMEWHRE } } } else { globalsound NO_KEY1 quote 1015 } } ifspritepal 10 { ifvarand ACCESSKEY2 8 { setvar CKEYCARDTILE 2568 setvar CKEYCARDPAL 10 setvar CUSTOMKEYCARDPOS 21 setvar KEYCARD_TEMP2 1 action UNLOCKING ifrnd 128 { globalsound OPEN_SESAME } else { ifrnd 128 { globalsound LETS_SEE } else { globalsound GETTIN_SOMEWHRE } } } else { globalsound NO_KEY1 quote 1015 } } ifspritepal 13 { ifvarand ACCESSKEY2 16 { setvar CKEYCARDTILE 2568 setvar CKEYCARDPAL 13 setvar CUSTOMKEYCARDPOS 21 setvar KEYCARD_TEMP2 1 action UNLOCKING ifrnd 128 { globalsound OPEN_SESAME } else { ifrnd 128 { globalsound LETS_SEE } else { globalsound GETTIN_SOMEWHRE } } } else { globalsound NO_KEY1 quote 1015 } } ifspritepal 14 { ifvarand ACCESSKEY2 32 { setvar CKEYCARDTILE 2568 setvar CKEYCARDPAL 14 setvar CUSTOMKEYCARDPOS 21 setvar KEYCARD_TEMP2 1 action UNLOCKING ifrnd 128 { globalsound OPEN_SESAME } else { ifrnd 128 { globalsound LETS_SEE } else { globalsound GETTIN_SOMEWHRE } } } else { globalsound NO_KEY1 quote 1015 } } ifspritepal 16 { ifvarand ACCESSKEY2 64 { setvar CKEYCARDTILE 2568 setvar CKEYCARDPAL 16 setvar CUSTOMKEYCARDPOS 21 setvar KEYCARD_TEMP2 1 action UNLOCKING ifrnd 128 { globalsound OPEN_SESAME } else { ifrnd 128 { globalsound LETS_SEE } else { globalsound GETTIN_SOMEWHRE } } } else { globalsound NO_KEY1 quote 1015 } } ifspritepal 30 { ifvarand ACCESSKEY2 128 { setvar CKEYCARDTILE 2568 setvar CKEYCARDPAL 30 setvar CUSTOMKEYCARDPOS 21 setvar KEYCARD_TEMP2 1 action UNLOCKING ifrnd 128 { globalsound OPEN_SESAME } else { ifrnd 128 { globalsound LETS_SEE } else { globalsound GETTIN_SOMEWHRE } } } else { globalsound NO_KEY1 quote 1015 } } } ifaction UNLOCKING { ifvare KEYCARD_TEMP2 1 { ifcount 8 { subvar CUSTOMKEYCARDPOS 1 ifvare CUSTOMKEYCARDPOS 9 { ifspritepal 12 { subvar ACCESSKEY2 1 } ifspritepal 11 { subvar ACCESSKEY2 2 } ifspritepal 15 { subvar ACCESSKEY2 4 } ifspritepal 10 { subvar ACCESSKEY2 8 } ifspritepal 13 { subvar ACCESSKEY2 16 } ifspritepal 14 { subvar ACCESSKEY2 32 } ifspritepal 16 { subvar ACCESSKEY2 64 } ifspritepal 30 { subvar ACCESSKEY2 128 } state checkcounterpart2 operateactivators LOTAGSAVED THISACTOR operaterespawns LOTAGSAVED operatemasterswitches LOTAGSAVED setvar KEYCARD_TEMP2 0 setvar CUSTOMKEYCARDPOS 0 action UNLOCKED } } ifvarl CUSTOMKEYCARDPOS 0 { setvar CUSTOMKEYCARDPOS 0 setvar KEYCARD_TEMP2 0 action LOCKED } } } ends useractor notenemy ACCESSSWITCH3 state CUSTOMACCESSSWITCH enda onevent EVENT_DISPLAYREST ifvarand ACCESSKEY2 1 { rotatesprite 100 20 HALFSIZE 0 15175 0 12 512 0 0 xdim ydim } ifvarand ACCESSKEY2 2 { rotatesprite 125 20 HALFSIZE 0 15175 0 11 512 0 0 xdim ydim } ifvarand ACCESSKEY2 4 { rotatesprite 150 20 HALFSIZE 0 15175 0 15 512 0 0 xdim ydim } ifvarand ACCESSKEY2 8 { rotatesprite 175 20 HALFSIZE 0 15175 0 10 512 0 0 xdim ydim } ifvarand ACCESSKEY2 16 { rotatesprite 200 20 HALFSIZE 0 15175 0 13 512 0 0 xdim ydim } ifvarand ACCESSKEY2 32 { rotatesprite 225 20 HALFSIZE 0 15175 0 14 512 0 0 xdim ydim } ifvarand ACCESSKEY2 64 { rotatesprite 250 20 HALFSIZE 0 15175 0 16 512 0 0 xdim ydim } ifvarand ACCESSKEY2 128 { rotatesprite 275 20 HALFSIZE 0 15175 0 30 512 0 0 xdim ydim } endevent onevent EVENT_DISPLAYWEAPON ifvarg CUSTOMKEYCARDPOS 0 { getplayer[THISACTOR].weapon_pos KEYCARD_TEMP3 getplayer[THISACTOR].kickback_pic KEYCARD_TEMP4 setplayer[THISACTOR].weapon_pos 10 setplayer[THISACTOR].kickback_pic 0 switch CUSTOMKEYCARDPOS case 0: break case 1: rotatesprite 80 134 NORMALSIZE 0 2565 0 0 0 0 0 xdim ydim break case 2: rotatesprite 80 134 NORMALSIZE 0 2565 0 0 0 0 0 xdim ydim break case 3: rotatesprite 80 134 NORMALSIZE 0 2565 0 0 0 0 0 xdim ydim break case 4: rotatesprite 80 134 NORMALSIZE 0 2565 0 0 0 0 0 xdim ydim break case 5: rotatesprite 120 134 NORMALSIZE 0 2564 0 0 0 0 0 xdim ydim break case 6: rotatesprite 120 134 NORMALSIZE 0 2564 0 0 0 0 0 xdim ydim break case 7: rotatesprite 120 134 NORMALSIZE 0 2564 0 0 0 0 0 xdim ydim break case 8: rotatesprite 120 134 NORMALSIZE 0 2564 0 0 0 0 0 xdim ydim break case 9: rotatesprite 160 134 NORMALSIZE 0 2563 0 0 0 0 0 xdim ydim break case 10: rotatesprite 160 134 NORMALSIZE 0 2563 0 0 0 0 0 xdim ydim break case 11: rotatesprite 160 134 NORMALSIZE 0 2563 0 0 0 0 0 xdim ydim break case 12: rotatesprite 160 134 NORMALSIZE 0 2563 0 0 0 0 0 xdim ydim break case 13: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break case 14: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break case 15: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break case 16: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break case 17: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break case 18: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break case 19: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break case 20: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break case 21: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break case 22: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break case 23: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break case 24: rotatesprite 160 134 NORMALSIZE 1024 CKEYCARDTILE 0 CKEYCARDPAL 260 0 0 xdim ydim break endswitch ifvarl CUSTOMKEYCARDPOS 1 { setplayer[THISACTOR].weapon_pos KEYCARD_TEMP3 setplayer[THISACTOR].kickback_pic KEYCARD_TEMP4 } break } ifvarg KEYCARD_TEMP7 0 { subvar KEYCARD_TEMP7 1 } endevent onevent EVENT_USE ifvare KEYCARD_TEMP7 1 { break } endevent onevent EVENT_SPAWN setvar ACCESSKEY2 0 setvar CUSTOMKEYCARDPOS 0 setvar KEYCARD_TEMP2 0 setvar KEYCARD_TEMP7 0 ifvare KEYCARD_TEMP 121 { setvar ACCESSKEY2 7 } endevent
The only thing you will probably have to change is the number of the sprite of the texture of the switch and the card, as well as the name of both, according to your needs. Keep in mind that I'm trying to add things to Duke Nukem Legacy 2.0 on my own. So if you're going to use this in some other mod or for your own mod, some small adjustments may be necessary, I think. I hope this code can serve as a basis to help newbies like me add new colors for cards and switches to the game in an easier and more accessible way, without having to spend time trying to figure out how to do it, as a facilitator. Don't forget that I'm still new to CON programming and therefore I still use artificial intelligence resources to help me identify, extract, assemble, organize and change codes for my needs, although even with this kind of help I don't always get what I need, so sometimes I have to come here and ask for help.
Here's an image to show what I did:


At least here in my PC it works.
#3594 Posted 11 December 2024 - 01:53 PM
gamevar ACCESSKEY2 0 1 gamevar CUSTOMKEYCARDPOS 0 0 gamevar KEYCARD_CURRENT_PAL 0 0 gamevar CKEYCARDPAL 0 0 gamevar CKEYCARDTILE 0 0 gamevar KEYCARD_TEMP 0 2 gamevar KEYCARD_TEMP2 0 2 gamevar KEYCARD_TEMP3 0 2 gamevar KEYCARD_TEMP4 0 2 gamevar KEYCARD_TEMP7 0 0
You can shorthand "gamevar" simply with "var". In fact there's a lot of shorthand stuff I'll be mentioning that makes reading code a lot easier.
For global gamevars (that is, those with the flag "0"), you don't actually have to declare the flag as gamevars default as global. Personally I don't use per-player gamevars either, unless you're writing a multiplayer mod then there's functionally no difference between global and per-player.
eventloadactor ACCESSCARD2 setactor[THISACTOR].xrepeat 28 setactor[THISACTOR].yrepeat 28 enda
You should use the EVENT_LOADACTOR event rather than eventloadactor, as eventloadactor and similar legacy EDuke functionality has been superceded by game events.
It's good practice to use curly braces to contain state, event, etc. code.
You can shorthand your setactor calls to "seta", and if you are working with THISACTOR then the spriteid brace can be omitted as well. So your code becomes:
onevent EVENT_LOADACTOR { seta .xrepeat 28 seta .yrepeat 28 } endevent
ifspritepal 12 { ifvarand ACCESSKEY2 1 { break } else { addvar ACCESSKEY2 1 setvar KEYCARD_TEMP7 30 globalsound DUKE_GET quote 43 palfrom 16 0 32 killit break } } ifspritepal 11 { ifvarand ACCESSKEY2 2 { break } else { [. . .] } } [. . .]
The curly braces with the "break" in them should be replaced by "nullop" which does what you are intending on doing here. In fact, using curly braces on a single command is a bad practice and can slow down CON performance and should be avoided.
You should use an "else" statement between these ifspritepal calls. This would make them a single conditional chain, rather than each block being evaluated. As it is, the script checks against each conditional even if it finds a successful branch. Technically this is resolved by your use of "break", but only because there is no other code after the ifspritepal block. If there was code after then that you needed to execute, you wouldn't be able to use break here in that way.
Like shorthanding "setactor" to "seta", any gamevar if conditions don't require the implicit usage of "var" or "varvar" in them. So "ifvarand" (or "ifvarvarand") just becomes "ifand", and "addvar" just becomes "add".
You also reuse a lot of code in this section, which you could put into a separate state and save code size and make things a lot more readable.
With these changes:
defstate getcard { set KEYCARD_TEMP7 30 globalsound DUKE_GET quote 43 palfrom 16 0 32 killit } ends [. . .] ifspritepal 12 { ifand ACCESSKEY2 1 nullop else { add ACCESSKEY2 1 state getcard } } else ifspritepal 11 { ifand ACCESSKEY2 2 nullop else { add ACCESSKEY2 2 state getcard } } [. . .]
Moving on...
eventloadactor ACCESSSWITCH3 { getactor[THISACTOR].pal KEYCARD_TEMP setactor[RETURN].pal KEYCARD_TEMP getactor[THISACTOR].hitag HITAGSAVED getactor[THISACTOR].lotag LOTAGSAVED setactor[THISACTOR].hitag 0 setactor[THISACTOR].lotag 0 setactor[THISACTOR].cstat 17 setactor[THISACTOR].clipdist 64 } enda
I don't understand what the "setactor[RETURN]" line is supposed to be doing here. I don't think it accomplishes anything, eventloadactor doesn't use RETURN. I think you meant to put THISACTOR here. Otherwise the same changes apply as mentioned in the earlier use of eventloadactor, and this block can be streamlined.
state checkcounterpart2 setvar KEYCARD_TEMP 0 whilevarn KEYCARD_TEMP 16384 { getactor[KEYCARD_TEMP].statnum KEYCARD_TEMP4 ifvarn KEYCARD_TEMP4 1024 { getactor[KEYCARD_TEMP].picnum KEYCARD_TEMP2 ifvare KEYCARD_TEMP2 ACCESSSWITCH3 { getactorvar[KEYCARD_TEMP].LOTAGSAVED KEYCARD_TEMP3 ifvarvare LOTAGSAVED KEYCARD_TEMP3 { setactor[KEYCARD_TEMP].picnum 15177 } } } addvar KEYCARD_TEMP 1 } ends
This code really sucks, but I don't blame you, because why it sucks is not immediately clear or well documented.
You should use "defstate" when defining new state blocks, and reserve using "state" when calling them from other locations in code.
The main thing is that while loops are really, really bad performance-wise. The exact reasons are technical in a way that I won't go into here, but whenever possible you should use a for loop instead of a while loop. For loops are, like, logarithmically more performant than while loops in CON. The while loop you're using here seems like it could even be replaced with a "for allsprites" loop, since it seems to be looking for any sprite with a matching LOTAGSAVED gamevar value. Also, when using for loops, it's not necessary to initialize the iterator gamevar to 0 as that's implied.
You can also directly compare sprite structs without assigning them to gamevars.
After changes:
defstate checkcounterpart2 { for KEYCARD_TEMP allsprites { ifn sprite[KEYCARD_TEMP].statnum 1024 ife sprite[KEYCARD_TEMP].picnum ACCESSSWITCH3 ife actorvar[KEYCARD_TEMP].LOTAGSAVED LOTAGSAVED seta[KEYCARD_TEMP].picnum 15177 } } ends
This code still kinda sucks but for different reasons. Checking the statnum for 1024 (invalid sprites) probably isn't necessary. You could probably also replace the allsprites loop (which is generally slow) with a more precisite "spritesofstatus", or shorthanded to "sprofstat" to look for just actors, assuming ACCESSSWITCH3 will always be an actor. Lastly, using magic numbers is always bad, so you should define 15177 somewhere and use that definition instead.
The only other real thing is down in the EVENT_DISPLAYWEAPON code, your switch case has "case 0" but you should change this to "default" to catch unexpected values.
The rest of the code seems to fall into a lot of these traps, especially lots of recycled code that could be a separate state block, and tons of curly braced single line commands. You do that a lot and it's pretty bad.
Happy coding.
#3595 Posted 11 December 2024 - 02:48 PM
btw I generally don't tell people about the abbreviations because when I see the non-abbreviated syntax it can indicate what era they copied the code from which can be useful information. On the for loop, I suspect it was modified from a whilevarn loop that did go through the entire sprite array and in that version the statnum 1024 check was not redundant. I don't think CON had for loops back when James made Nuclear Showdown. So most likely eniojr changed the loop type (which was a good thing to do) but he didn't know what the statnum check was for so he left that in.
#3596 Posted 11 December 2024 - 02:52 PM

This post has been edited by Mark: 11 December 2024 - 02:53 PM
#3597 Posted 11 December 2024 - 03:10 PM
Danukem, on 11 December 2024 - 02:48 PM, said:
btw I generally don't tell people about the abbreviations because when I see the non-abbreviated syntax it can indicate what era they copied the code from which can be useful information. On the for loop, I suspect it was modified from a whilevarn loop that did go through the entire sprite array and in that version the statnum 1024 check was not redundant. I don't think CON had for loops back when James made Nuclear Showdown. So most likely eniojr changed the loop type (which was a good thing to do) but he didn't know what the statnum check was for so he left that in.
For loops are definitely a relatively recent addition.
I'd have to double check but I am 99% certain that "notenemy" useractors start awake and never go asleep. Specifically it's the htflag SFLAG_BADGUY is what enables the sleeping behavior (among a lot of other things, obviously). There are some hardcoded actors that start the map as STAT_ZOMBIEACTOR and so they only wakeup when you see them, but that was a "it's the year 1996 and this needs to run on my 486" solution, and useractor notenemy actors don't do that by default. I could be wrong, I'm not 100%, but I'm pretty positive.
That being said, a single allsprites loop when you use a button isn't the worst thing ever and shouldn't cause a noticeable performance hit, so its not necessary to change it. My point is more that you should use the tool the job calls for, and using allsprites every time you need to do something is probably not great. Although it would still be better than using a while loop!
#3598 Posted 11 December 2024 - 03:20 PM
Well, my code sucks, but at least worked for me for whatever reason... and within a mod! At least the game runs normally in my computer.
Now I'm working into adding new effects to the mod, like JUMPAD from Dukeplus. It worked somehow, but it worked! Maybe because that was a more simple effect. It's just like the mod, with a forward pushing effect. And I even got a higher height jump than the mod itself. So JUMPAD effect is done.
The next step is to make ladder and maybe mantling effect work, also like Dukeplus. I saw that maybe there's one same logic or movement mechanics interconnected between several effects such as mantling, ladder, dodge and realrunning, like pythagoras for example. I put several states and events in my code from USERPLUS.CON, DUKEPLUS.CON and PLAYERPLUS.CON related to ladder, mantling and dodge, but still only JUMPAD works. Don't know if dodge effect is needed for mantling and ladder effects. If not, I'll leave that for later, after mantling and ladder are done.
Dukeplus in Legacy mod! That rocks!!! At least for some effects.
I will show my code latter in separate parts, maybe in my next post.
At least now I can use a jump pad like that of Rise of The Triad in my maps, to make rooms only accessible though them, if you don't have a jetpack or if you want to save on jetpack. And also at least now I can use several colors for my keycards, so more options for searching for accesscards and more puzzles in my maps too. I'm thinking of adding the blue, red and yellow colors for my custom accesscard and accessswitch actors, for everything to be customized. Maybe not, I still haven't decided.
#3599 Posted 11 December 2024 - 05:57 PM
Mark, on 11 December 2024 - 02:52 PM, said:

If you have code that sucks, feel free to post it. My point isn't to fix anyone's stuff, all I did here was point out some issues of usage and ways to improve readability. My goal is to help people find ways of improving their own code.
#3600 Posted 11 December 2024 - 07:16 PM
#3601 Posted 11 December 2024 - 08:34 PM
Reaper_Man, on 11 December 2024 - 03:10 PM, said:
You are half right. Yes, they do start awake but they will go to sleep and quite quickly too if they are far away from and not in view of the player when the map starts. And after that they follow the rules of any other actor about falling asleep / waking up.