Duke4.net Forums: EDuke32 Scripting - Duke4.net Forums

Jump to content

  • 124 Pages +
  • « First
  • 118
  • 119
  • 120
  • 121
  • 122
  • Last »
  • You cannot start a new topic
  • You cannot reply to this topic

EDuke32 Scripting  "CON coding help"

User is online   VGames 

#3571

View PostReaper_Man, on 03 November 2024 - 09:48 AM, said:

Actors go asleep in 2 ways, changing their statnum and the .httimetosleep property. You can check their .picnum to see if it matches the enemy tile ID, and then check if their statnum is set to STAT_ZOMBIEACTOR and if so set them back to STAT_ACTOR. This will turn them back into regular actors running code. Actors turn into Zombies when their "sleep time" counter exceeds 32767 (and other conditions like being too far away). So you probably want to set the .httimetosleep back to 0 when you force them out of the Zombie state to prevent them from instantly falling asleep again.


Cool man. That explains a lot.

By the way I ended up using the code from AWOL like you said to set up targeting reticles that pop up on enemies when they are on the other side of walls. It works pretty dang good thanks to you, so thanks for allowing me to use some code from AWOL. However, I noticed that when enemies are higher than me, such as a Liztroop flying, the targets are much higher than the actual enemy position on my screen. Were these health stats that appear above the bots in AWOL not setup to accommodate flying bots or bots that were higher than you because the bots in AWOL don't ever fly around or go up above you often? Can this be fixed? It's not a huge deal for me since you can only see enemies on the other side of a wall that you're somewhat close to and enemies aren't necessarily in the air or higher than you anyways while using this see through walls mechanic. I was just wanted to fix it if it was possible just in case.
0

User is offline   Reaper_Man 

  • Once and Future King

#3572

Like I said, the vertical desync. If the problem is because of precision issues with .horiz, then I don't know if the problem can be solved. Otherwise it's an issue in the math calculating the Z-difference, I'd look at that code section first. I don't think it's a screen drawing precision issue but you could rule it out using the ROTATESPRITE_FULL16 flag (and changing the screen drawing values accordingly)
0

User is online   VGames 

#3573

View PostReaper_Man, on 03 November 2024 - 07:10 PM, said:

Like I said, the vertical desync. If the problem is because of precision issues with .horiz, then I don't know if the problem can be solved. Otherwise it's an issue in the math calculating the Z-difference, I'd look at that code section first. I don't think it's a screen drawing precision issue but you could rule it out using the ROTATESPRITE_FULL16 flag (and changing the screen drawing values accordingly)

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

0

#3574

I had a couple questions involving changing the chaingun cannon to something more akin to the plasma rifle from the LameDuke beta. Is it possible, through CON editing or something more advanced, to:

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

User is offline   Danukem 

  • Duke Plus Developer

#3575

If you are making a mod with a new character and weapons, you'll need to learn a ton of stuff and it won't be easy, although there are many released mods that already do that and you can look at for examples of how to do things. My advice is just accept from the start that you will need to make your own chaingun with its own sprites, its own ammo actor, its own separate display code, etc. Trying to piggyback on the hardcoded chaingun will limit you severely and if your mod "doesn't interfere with anything already in place" then hacking the chaingun for your new weapon seems like a nonstarter anyway.

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

User is offline   eniojr 

#3576

I'm having trouble to create new interactive buttons. I tried looking some mods, tried to replicate the code, like Memories Mod, but with no results. I just want to create a new button with 2 new textures (off and on). I also tried keycard buttons and new keycards, but also without results.
0

User is offline   Danukem 

  • Duke Plus Developer

#3577

Why do you need new buttons? You could just put your new textures on the existing button tile numbers.
0

User is offline   eniojr 

#3578

View PostDanukem, on 27 November 2024 - 11:32 PM, said:

Why do you need new buttons? You could just put your new textures on the existing button tile numbers.


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. :D
0

User is offline   Reaper_Man 

  • Once and Future King

#3579

The problem with wholesale copying code from other mods without actually understanding what those things are doing, is you don't know why they aren't working when you just change some names around.

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

User is offline   eniojr 

#3580

Quote

OThe problem with wholesale copying code from other mods without actually understanding what those things are doing, is you don't know why they aren't working when you just change some names around.

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

User is offline   Danukem 

  • Duke Plus Developer

#3581

If your new buttons are actors, and you intend to make or modify other actors, then learning the CON fundamentals of action, move and other basic commands is worthwhile and perhaps even necessary. You should be able to open up the GAME.CON from the Atomic edition, look at the code for some arbitrary actor and be able to understand what it's doing. You should also be able to create your own actor from scratch that does simple things that could be done in the original game like display certain frames of animation for certain amounts of time when interacted with (just one example). If you had that basic amount of proficiency, then knowing that operateactivators, operatemasterswitches and operaterespawns are things you would want a working button to do would already give you enough to easily code the actor without any further help. [Er...I suppose you would probably get stuck on not knowing EVENT_LOADACTOR but you could still make it work without that]. Copying and pasting code you don't understand and then struggling to modify the pasted code with extremely limited knowledge is very inefficient. It's also unappealing for those of us who do understand it: it comes off as "help me take" rather than "help me learn".
0

User is offline   eniojr 

#3582

Finally, I managed to make a new custom button in the game. Here is the script:


/////////////////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.
0

User is offline   Danukem 

  • Duke Plus Developer

#3583

That's way too much to read. Glancing at the rotatesprite commands, I see that pal is 0 in all cases though so I don't see how you could display different colored cards with that.
0

User is offline   eniojr 

#3584

The main problem for now is related to the layers. I just can't make the animation happen behind the status bar, like that one in the game. It happens in front of the status bar.

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

0

User is offline   eniojr 

#3585

Here is a shortened version of the animation script, for easier reading:

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

0

User is offline   Danukem 

  • Duke Plus Developer

#3586

View Posteniojr, on 02 December 2024 - 07:54 AM, said:

The main problem for now is related to the layers. I just can't make the animation happen behind the status bar, like that one in the game. It happens in front of the status bar.

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

User is offline   eniojr 

#3587

No, I haven't explored any code related to weapons yet, as I don't plan on creating or modifying weapons in the game. Dealing with weapons is even more complex.
0

User is offline   Danukem 

  • Duke Plus Developer

#3588

You don't understand what I meant but I guess the custom card code that James wrote utilizes access_incs in the player struct so the weapon display is already disabled.
0

User is online   VGames 

#3589

When using EVENT_DAMAGEWALL how do you check to see if the wall was damaged by RADIUSDAMAGE from an explosion and it wasn't from a bullet or some other projectile?
0

User is offline   Reaper_Man 

  • Once and Future King

#3590

https://wiki.eduke32...VENT_DAMAGEWALL

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

1

User is online   VGames 

#3591

Ok that makes perfect sense. I was getting confused by the userdef.return stuff. Thanks a lot. I'll give it a shot.
0

User is offline   Reaper_Man 

  • Once and Future King

#3592

In this instance, return is a userdef property. It's also an array, so to access different array indices you use the second value (in this case "1"). There's not too many properties that are exposed arrays, htg_t is the main one that know of and use a lot.
1

User is offline   eniojr 

#3593

I finally managed to create cards with new colors, from a new actor for accesscard and accessswitch. I based it on the codes from Nuclear Showndown. This includes animation for the card and I even managed to put the animation behind the status bar, like in the original game. I just couldn't make it so that when interacting with the switch, the player would also interact with the wall, which could cause the sound to interrupt when activating the switch. But this also seems to happen in the mod in relation to the custom switches.

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:

Posted Image

Posted Image

At least here in my PC it works.
1

User is offline   Reaper_Man 

  • Once and Future King

#3594

I'm putting off doing other work so have a little bit of a code review. I take it you're new to CON. From your other comments it seems like you're pulling a lot of this from other mods. Hopefully this will help you get a better understanding of the language.

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

User is offline   Danukem 

  • Duke Plus Developer

#3595

I'm pretty sure ACCESSSWTICH3 could be either statnum 1 or 2, since it will sometimes be asleep

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

User is online   Mark 

#3596

This is great info. However, it made me realize ReaperMan would have to quit her daytime job to have enough time to go thru and analyze the sloppy code in my projects. :lol:

This post has been edited by Mark: 11 December 2024 - 02:53 PM

0

User is offline   Reaper_Man 

  • Once and Future King

#3597

View PostDanukem, on 11 December 2024 - 02:48 PM, said:

I'm pretty sure ACCESSSWTICH3 could be either statnum 1 or 2, since it will sometimes be asleep

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!
0

User is offline   eniojr 

#3598

Ok, I didn't have that type of understanding about codes, it's new for me. I just put the codes from the mod in a custom file and tried to make adaptations to use in legacy mod, with the help of AI. Without AI aid, I can't make complex coding like that to work, and it still has a limit for that. But at least I have learned more things about state, actor and event through search, trial and error, and a bit more about things like cstate, setvar, some if conditionals (in a very limited way), ends, enda, etc. I just used a format more similar to what was in the mod.

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

User is offline   Reaper_Man 

  • Once and Future King

#3599

Well, good luck.

View PostMark, on 11 December 2024 - 02:52 PM, said:

This is great info. However, it made me realize ReaperMan would have to quit her daytime job to have enough time to go thru and analyze the sloppy code in my projects. :lol:

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

User is offline   eniojr 

#3600

Ok, I'll try to simplify that accessswitch and accesscard code.
0

Share this topic:


  • 124 Pages +
  • « First
  • 118
  • 119
  • 120
  • 121
  • 122
  • Last »
  • You cannot start a new topic
  • You cannot reply to this topic


All copyrights and trademarks not owned by Voidpoint, LLC are the sole property of their respective owners. Play Ion Fury! ;) © Voidpoint, LLC

Enter your sign in name and password


Sign in options