EDuke32 Scripting "CON coding help"
#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
}
endeventThe 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
endaYou 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
}
endaI 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
}
endsThis 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
}
}
endsThis 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.
#3602 Posted 12 December 2024 - 05:57 AM
I haven't a clue how to change over. One example of a while loop IIRC. A useractor waiting for a keyboard input while performing some action like walking/moving. The code is looping and waiting for an ifhitspace command. Or waiting for ifpdistl to reach a certain value before performing another action. If those are indeed while loops what would be a for loop example?
#3603 Posted 12 December 2024 - 06:10 AM
Mark, on 12 December 2024 - 05:57 AM, said:
I haven't a clue how to change over. One example of a while loop IIRC. A useractor waiting for a keyboard input while performing some action like walking/moving. The code is looping and waiting for an ifhitspace command. Or waiting for ifpdistl to reach a certain value before performing another action. If those are indeed while loops what would be a for loop example?
https://wiki.eduke32.com/wiki/For
#3604 Posted 12 December 2024 - 07:04 AM
Like I said, post whatever code you might be worried about if you think you're using while loops in a bad way, otherwise the other stuff I mentioned is probably more relevant to 90% of scripts.
#3605 Posted 12 December 2024 - 07:33 AM
My coding is very simplistic so maybe any slight performance hit isn't an issue. But I thought it couldn't hurt to try changing to for loops if I had the skill for it.
This post has been edited by Mark: 12 December 2024 - 07:42 AM
#3606 Posted 12 December 2024 - 04:53 PM
I'm basically trying to add Dukeplus's movement effects to Legacy. In other words, the JUMPAD effect works successfully!
Now my focus is on the stairs. I've tried everything, even with the help of my artificial assistant, but I'm still just going around in circles, not knowing how to make this effect work in Legacy. I put all the events and states I could find in the script in USERPLUS.CON, PLAYERPLUS.CON and DUKEPLUS.CON. I'm not sure, but I suspect that some code or other escaped my notice in these files, or there may be specific errors that I still don't have a clue about. I also tried to make the mantling and dodge effects, but without success. Out of desperation I even added onevent EVENT_JUMP and others of the sort, but still couldn't do it. There's even the pythagoras state, but without success. Another problem could be the order of the codes, but I don't have a clear clue about that. There are even codes within the states and events that may be related to things that I don't intend to add to the mod. But as I'm afraid of changing the code too much and ending up doing something wrong, I left such codes.
I tried to make this work for DAYS!
One thing that really made it difficult for me was the fact that code for the same mechanic seems to be spread across multiple files. That's why I always prefer to put everything related to something in a single file. The day I make a real mod, I'll put each type of thing in its own file, so I can organize myself better and avoid conflicts and confusion. But unfortunately, sharing code between files is something that is common in game mods, unfortunately, even more so when it comes to complex mechanics of effects and movement. For someone like me (newbie in coding) who wants to extract a particular effect or function, it gets complicated and very frustrating!
Here is a picture of how the icons related to the effects look in Mapster32. "J" is the JUMPAD, while "L" is the ladder effect.
The way the icons are on the map is exactly like on the Dukeplus effects test map.

And now, the code (that sucks, so prepare yourself)
Because the script is BIG, I'll separate in parts.
Note: At least on Legacy and on my computer, there were no compilation errors. The desired effects just didn't occur.
/////////////////////////////////////////////
Part 1: Definitions and variations
// LADDER.CON - Advanced Player Movement Mechanics // Global Configuration Flags define MANTLING YES define DODGING YES define FREERUNNER YES define REALRUNNING YES define MANTCHECK 6 define MANTDIST 480 define DODGE_IMPULSE_MULTIPLIER 2 define DODGE_DISTANCE 640 // DEFINES FOR RUNNING: THESE DO NOTHING UNLESS REALRUNNING IS ON define SPEED1 45000 // the speed that you start at when you begin to run define SPEED2TIME 30 // the number of ticks of acceleration before reaching RUNNINGSPEED define RUNACCEL 256 // the rate of acceleration between SPEED1 and SPEED2 define LADDER 2951 define MOVEMENT 2952 define LADDER_CLIMB_SPEED -256 define LADDER_DETECT_DIST 480 define LADDER_STATE_NONE 0 define LADDER_STATE_CLIMBING 1 define LADDER_STATE_DISMOUNTING 2 define pforward 1 define pbackward 2 gamevar cannonid -1 1 gamevar sleeping 0 1 gamevar numallies 0 0 gamearray ptrails 100 gamevar ptrailtimer 0 1 gamevar dpsounds YES 0 gamevar menunag 1 1 gamevar nomenu 0 0 gamevar nagpos 900 1 gamevar menutoggle 0 1 gamevar ONCAR 0 1 gamevar timer 0 0 gamevar canmantle MANTLING 0 gamevar mantling 0 1 gamevar mantwait 0 1 gamevar mantwaittime 0 1 gamevar mantcheck 0 1 gamevar mantz 0 1 gamevar jumped 0 1 gamevar backview 0 1 gamevar holding -1 1 gamevar pickup 0 1 gamevar holdingpic 0 1 gamevar drinksoda 0 1 gamevar monstflags 0 2 gamevar hitag 0 2 gamevar lotag 0 2 gamevar spriteid 0 0 gamevar monstatus 0 2 gamevar target -1 2 gamevar candodge DODGING 0 gamevar dodge 0 1 gamevar botdodge 0 2 gamevar dodgeagain 0 1 gamevar dodgeang 0 1 gamevar nofalldamage 0 1 gamevar ftap 0 1 gamevar fpresstime 0 1 gamevar btap 0 1 gamevar bpresstime 0 1 gamevar ltap 0 1 gamevar lpresstime 0 1 gamevar rtap 0 1 gamevar rpresstime 0 1 gamevar fhold 0 1 gamevar bhold 0 1 gamevar lhold 0 1 gamevar rhold 0 1 gamevar mx 0 0 gamevar my 0 0 gamevar mz 0 0 gamevar initx 0 2 gamevar inity 0 2 gamevar initz 0 2 gamevar walljump 0 1 gamevar jumptap 0 1 gamevar jumpadxvel 0 1 gamevar onladder 0 1 gamevar topladder 0 2 gamevar laddervel 0 1 gamevar lastladderx 0 1 gamevar lastladdery 0 1 gamevar laddersound -1 1 gamevar scaled NO 0 gamevar doubled NO 0 gamevar onblock 0 1 gamevar bits 0 1 gamevar thrust 0 1 gamevar extbits 0 1 gamevar fpress 0 1 gamevar bpress 0 1 gamevar mysector -1 2 gamevar mywall -1 2 gamevar underwater 0 2 gamevar xvel 0 0 gamevar yvel 0 0 gamevar zvel 0 0 gamevar tempc 0 0 gamevar tempd 0 0 gamevar tempe 0 0 gamevar zdist 0 0 gamevar xydist 0 0 gamevar xydist2 0 0 gamevar angvar 0 0 gamevar canseeplayer 0 2 gamevar canshootplayer 0 2 gamevar mysin 0 1 gamevar mycos 0 1 gamevar hitsector 0 1 gamevar hitwall 0 1 gamevar hitwall2 0 1 gamevar nextsector 0 1 gamevar hitsprite -1 1 gamevar scannedsprite -1 1 gamevar hitx 0 2 gamevar hity 0 2 gamevar hitz 0 2 gamevar clipmask 4294901808 0 gamevar hp 0 2 gamevar slowrunaccel REALRUNNING 0 gamevar pspeed 0 1 gamevar camshake 0 1 gamevar runcount 0 1 gamevar runflag 0 1 gamevar strafedir 0 1 gamevar laststrafedir 0 1 gamevar forbackdir 0 1 gamevar lastforbackdir 0 1 gamevar oposxv 0 1 // velocities from last tick gamevar oposyv 0 1 gamevar oposzv 0 1 gamevar offground 0 1 // counter gamevar weight 0 2 gamevar activator 0 2 gamevar initshade 0 2 gamevar playerally 0 2 gamevar pal 0 2 gamevar peractor1 0 2 gamevar peractor2 0 2 gamevar peractor3 0 2 gamevar fallflag 0 2 gamevar peractor4 0 2 gamevar peractor5 0 2 gamevar peractor6 0 2 gamevar peractor7 0 2 gamevar target2 -1 2 gamevar intensity 0 2 gamevar mtype 0 2 gamevar countvar 0 2 gamevar countvarb 0 2 gamevar myspawner -1 2 gamevar teleported 0 2 gamevar digx 0 1 gamevar digy 0 1 gamevar digz 0 1 gamevar orientation 0 1 gamevar shade 0 1 gamevar superkicking 0 1 gamevar superkickdone 0 1 gamevar spinkick 0 1 gamevar reversekick 0 1 gamevar kicktarg -1 1 gamevar kickimpact 0 1 define KENERGY 780 gamevar kickenergy KENERGY 1 action PSTAND 0 1 5 1 1
/////////////////////////////////////////////
Part 2: Pythagoras and JUMPAD codes (that seemed to work somehow)
state pythagoras
setvarvar xydist x
subvarvar xydist hitx
mulvarvar xydist xydist
setvarvar tempb y
subvarvar tempb hity
mulvarvar tempb tempb
addvarvar xydist tempb
sqrt xydist xydist
ends
/////////////////////////////////////////////
eventloadactor JUMPAD
readgamevar scaled
getactor[THISACTOR].extra monstflags
ifvare monstflags -1 setvar monstflags 0
getactor[THISACTOR].lotag lotag
getactor[THISACTOR].hitag hitag
// Default hitag if not set
ifvare hitag 0 setvar hitag 640
// Initialize velocity components
getactor[THISACTOR].xvel initx
getactor[THISACTOR].yvel inity
ifvare inity 0 setvar inity 26
getactor[THISACTOR].zvel initz
mulvar initz -8
ifvare scaled YES
{
// More controlled scaling
mulvar initx 1.5 // Less aggressive horizontal scaling
mulvar initz 2 // More vertical boost
}
// Ensure minimum and maximum velocity limits
ifvarg initx 1024 setvar initx 1024
ifvarg initz 512 setvar initz 512
// Optional scaling for jump pad
ifvare scaled YES
{
mulvar initx 2
mulvar initz 3
divvar initz 2
}
ifvare candodge YES
{
ifvarn jumpadxvel 0
{
mulvarvar xvel jumpadxvel
mulvarvar yvel jumpadxvel
}
getincangle dodgeang angvar sprite[spriteid].ang
}
enda
/////////////////////////////////////////////
// Jump Pad Activation Logic
useractor notenemy JUMPAD 0
ifvare DODGING NO break // Global dodge disable
ifvarn lotag 1 break
cstat 32768
getplayer[THISACTOR].i spriteid
ldist xydist THISACTOR spriteid
// Distance-based jump pad activation
ifvarvarl xydist hitag
{
getplayer[THISACTOR].falling_counter temp
// Falling counter logic
ifvarg temp 8
{
ifpdistg 1536 setvar temp 0
}
else
{
ifpdistl 1024 setvar temp 1
else ifpdistl 8192 ifvarn dodge 0 setvar temp 1
else setvar temp 0
}
// Jump pad activation
ifvarn temp 0
{
getplayer[THISACTOR].i spriteid
getactor[spriteid].z mz
subvar mz 8192
setactor[spriteid].z mz
getplayer[THISACTOR].posz z
subvar z 8192
setplayer[THISACTOR].posz z
setplayer[THISACTOR].jumping_counter 0
setplayer[THISACTOR].jumping_toggle 0
setplayer[THISACTOR].poszv initz
getplayer[THISACTOR].ang angvar
cos xvel angvar
sin yvel angvar
mulvar xvel 256
mulvar yvel 256
setplayer[THISACTOR].posxv xvel
setplayer[THISACTOR].posyv yvel
getactor[THISACTOR].ang dodgeang
setvarvar dodge inity
setvarvar jumpadxvel initx
setplayer[THISACTOR].falling_counter 0
setvar nofalldamage 1
soundonce LAUNCHSND
}
}
ifvare candodge YES
{
ifvarn dodge 0
{
setvarvar jumpadxvel initx
mulvar jumpadxvel DODGE_IMPULSE_MULTIPLIER
divvar initz 2
}
}
enda/////////////////////////////////////////////
Part 3: Codes related to ladder (the only thing seemed to work was related to extra value that made "L" sprite invisible. The rest... nothing!)
eventloadactor LADDER
{
getactor[THISACTOR].extra monstflags
setactor[THISACTOR].cstat 32768
setactor[THISACTOR].extra -1
getactor[THISACTOR].hitag hitag
getactor[THISACTOR].lotag lotag
setvar monstatus 0
setvar mtype 0
setvar myspawner -1
setactor[THISACTOR].clipdist 32
setactor[THISACTOR].xrepeat 32
setactor[THISACTOR].yrepeat 32
}
enda
/////////////////////////////////////////////
state laddercheck
{
getplayer[THISACTOR].i spriteid
ifvarn onladder 0 break
setvar temp 0
whilevarn temp 16384
{
getactor[temp].picnum picnum
ifvare picnum LADDER ifvarvarn temp THISACTOR
{
ldist xydist temp spriteid
ifvarl xydist LADDER_DETECT_DIST
{
getactor[temp].z mz
getplayer[THISACTOR].posz z
ifp pducking subvar z 4096
ifvarvarg z mz
{
addvar mz 16384
ifvarvarl z mz
{
setvarvar myspawner temp
setvar mtype 1
setvarvar topladder mz
getactor[temp].x lastladderx
getactor[temp].y lastladdery
break
}
}
}
}
addvar temp 1
}
}
ends
/////////////////////////////////////////////
state laddercode
{
ifvare onladder 0 break
setvar mantling 0
setvar dodge 0
setvar walljump 0
setplayer[THISACTOR].horiz 0
ifaction PSTAND nullop else action PSTAND
setplayer[THISACTOR].falling_counter 0
ifvare fpress 1
{
setvar laddervel LADDER_CLIMB_SPEED
soundonce DUKE_GRUNT
}
else ifvare bpress 1
{
setvar laddervel 256
soundonce DUKE_GRUNT
}
else
{
setvar laddervel 0
setplayer[THISACTOR].posxv 0
setplayer[THISACTOR].posyv 0
setplayer[THISACTOR].posx lastladderx
setplayer[THISACTOR].posy lastladdery
}
setplayer[THISACTOR].poszv laddervel
getplayer[THISACTOR].posz z
ifvarvarg z topladder
{
setvar onladder 0
break
}
ifp pjumping
{
setvar onladder 0
setvar laddervel -512
}
else
{
subvar onladder 1
}
}
ends
/////////////////////////////////////////////
useractor notenemy LADDER 0
{
ifp palive
ifvare mantling 0
ifvare dodge 0
{
getplayer[THISACTOR].i spriteid
ldist xydist THISACTOR spriteid
ifvarvarl xydist LADDER_DETECT_DIST
{
state laddercheck
ifvare mtype 1
{
setvar onladder 15
setplayer[THISACTOR].falling_counter 0
setvar nofalldamage 1
state laddercode
}
}
}
}
enda/////////////////////////////////////////////
Part 4: Codes related to mantling (no hint on how to make this work)
state checkwall // checks to see if there is a close wall to grab onto
// mantling will be set to 1 if the answer is yes, 0 otherwise
ifvare MANTLING NO break // Global mantle disable
ifp pjumping
{
state checkwall
ifvare mantling 1
{
getplayer[THISACTOR].posz mantz
setplayer[THISACTOR].poszv 256
}
}
setvar mantling 0
getactor[THISACTOR].z z
getactor[THISACTOR].x x
getactor[THISACTOR].y y
getactor[THISACTOR].sectnum mysector
getactor[THISACTOR].ang angvar
setvar zdist 0
cos mycos angvar
sin mysin angvar
hitscan x y z mysector mycos mysin zdist hitsector hitwall hitsprite hitx hity hitz clipmask
state pythagoras
setvarvar xydist2 xydist // saves the distance
ifvarn hitsprite -1
{
getactor[hitsprite].cstat tempb
ifvarand tempb 32768 break // Skip invisible sprites
ifvarand tempb 1 break // Skip non-solid sprites
getactor[hitsprite].picnum picnum
}
subvar z 1536
hitscan x y z mysector mycos mysin zdist hitsector hitwall2 hitsprite hitx hity hitz clipmask
state pythagoras
ifvarn hitsprite -1
subvar z 4096
setvar hp 10
whilevarn hp 0
{
setvar initcstat 1
hitscan x y z mysector mycos mysin zdist hitsector hitwall hitsprite hitx hity hitz clipmask
state pythagoras
ifvarn hitsprite -1 ifvarl xydist MANTDIST getactor[hitsprite].cstat initcstat
setvarvar xydist2 xydist
subvar z 512 //256
hitscan x y z mysector mycos mysin zdist hitsector hitwall2 hitsprite hitx hity hitz clipmask
state pythagoras
ifvarn hitsprite -1 ifvarl xydist MANTDIST
{
getactor[hitsprite].picnum picnum
ifvarn picnum BGRATE1 ifvarn picnum FANSPRITEBROKE
getactor[hitsprite].cstat initcstat
}
ifvarg xydist2 MANTDIST nullop else
ifvare hitsprite -1 ifvare hitwall -1 nullop else
ifvarn hitwall -1 ifvarvare hitwall hitwall2 nullop else
ifvarand initcstat 1
{
ifvarvarg xydist xydist2
{
setvar mantling 1
ifvare hitsprite -1
setvar mantling 1 else
{
getactor[hitsprite].cstat tempb
ifvarand tempb 32768 nullop else
ifvarand tempb 1 setvar mantling 1
}
}
else ifvarn hitsprite -1
{
ifvare picnum BGRATE1
setvar mantling 1
ifvare picnum FANSPRITEBROKE
setvar mantling 1
}
}
subvar hp 1
ifvare mantling 1 setvar hp 0 //10
subvar z 512 // 256
}
ends
/////////////////////////////////////////////
state mantlingcode
ifvarn onladder 0 { setvar mantling 0 break }
ifvare MANTLING NO break
ifvare DODGING NO break
ifonwater nullop else
ifonwater nullop else
ifvare scaled NO
{
// ifp ponsteroids setvar tempb 901 else
setvar tempb 721
ifvarvare player[THISACTOR].jumping_counter tempb setplayer[THISACTOR].jumping_counter 0
}
ifp ponground ifvare jumped 1 setvar jumped 0
ifvarl mantling 0 addvar mantling 1
ifvare mantling 1 addvar mantwait 1 else setvar mantwait 0
ifvarn onladder 0 { setvar mantling 0 break }
ifvarg dodge 0 { setvar mantling 0 break }
ifvarn holding -1 { setvar mantling 0 break }
ifp pjetpack { setvar mantling 0 break }
ifvare mantling 0 ifvare jumpadxvel 0
{
getplayer[THISACTOR].posx x
getplayer[THISACTOR].posy y
getactor[THISACTOR].z z
getplayer[THISACTOR].cursectnum mysector
ifvare mysector -1 getsector[THISACTOR].floorz mz else
getflorzofslope mysector x y mz // mz is the return var
subvarvar mz z // mz is now the distance to the ground
setvar temp 0
ifvarg mz 6144 setvar temp 1
ifvarg underwater 0
{
ifvarg mz 3072 setvar temp 1
ifvarand bits 1 nullop else setvar temp 0
}
ifvare temp 1
{
getplayer[THISACTOR].poszv zvel
ifvare jumped 1 setvar tempb 0 else setvar tempb 1536
ifvarg underwater 0 setvar zvel 2048
//ifonwater setvar zvel 2048
//ifinwater setvar zvel 2048
ifvarvarg zvel tempb
{
state checkwall
ifvare mantling 1
{
getplayer[THISACTOR].posz mantz
ifvarg underwater 0
setplayer[THISACTOR].sound_pitch 0
sound DUKE_GRUNT
wackplayer
getplayer[THISACTOR].posz z
subvar z 512
setplayer[THISACTOR].posz z
shiftvarr zvel 7
addvar zvel 3
setvarvar mantwaittime zvel
ifvarg mantwaittime 40 setvar mantwaittime 40
}
}
}
}
setplayer[THISACTOR].poszv 256
ifvarg mantling 0
{
ifvare mantling 1 // hanging there, possibly strafing
{
// More controlled horizontal movement during mantle
getplayer[THISACTOR].posxv xvel
getplayer[THISACTOR].posyv yvel
divvar xvel 4 // Even more reduced horizontal movement
divvar yvel 4
setplayer[THISACTOR].posxv xvel
setplayer[THISACTOR].posyv yvel
setplayer[THISACTOR].falling_counter 0
setplayer[THISACTOR].posz mantz
setplayer[THISACTOR].poszv -256 // 0
state checkwall
ifvare mantling 0
{
ifvarg underwater 0 ifvarand bits 1 setvar mantling 2 else
ifvarg mantcheck 0 setvar mantling 1
} else setvar mantcheck 6 // 6 ticks grace period
}
else
{
setplayer[THISACTOR].poszv -1536
getplayer[THISACTOR].ang angvar
cos xvel angvar
sin yvel angvar
mulvar xvel 64
mulvar yvel 64
setplayer[THISACTOR].posxv xvel
setplayer[THISACTOR].posyv yvel
getactor[THISACTOR].z z
getactor[THISACTOR].x x
getactor[THISACTOR].y y
getactor[THISACTOR].sectnum mysector
getactor[THISACTOR].ang angvar
setvar zdist 0
cos mycos angvar
sin mysin angvar
hitscan x y z mysector mycos mysin zdist hitsector hitwall hitsprite hitx hity hitz clipmask
state pythagoras
ifvarg xydist 384 ifvarg mantling 5 setvar mantling -10
else
ifvarand bits 1 addvar mantling 1 else setvar mantling -10
ifvarg mantling 23 setvar mantling -10
setplayer[THISACTOR].jumping_toggle 1
}
}
ifvare candodge YES
{
ifvarg dodge 0
{
// More precise dodge velocity reduction
setvarvar xvel jumpadxvel
setvarvar yvel jumpadxvel
mulvar xvel DODGE_IMPULSE_MULTIPLIER
mulvar yvel DODGE_IMPULSE_MULTIPLIER
// Gradual dodge cooldown
addvar dodgeagain 1
ifvarg dodgeagain DODGE_DISTANCE
{
setvar dodge 0
setvar dodgeagain 0
setvar jumpadxvel 0 // Reset jump pad velocity
}
}
}
ends/////////////////////////////////////////////
Part 5: Codes related to dodge (no hint on how to make this work)
state dodgewallcheck // checks to see if there is a close wall in the actor's path at angvar
getactor[THISACTOR].z z
subvar z 6144
getactor[THISACTOR].x x
getactor[THISACTOR].y y
getactor[THISACTOR].sectnum mysector
setvar zdist 0
cos mycos angvar
sin mysin angvar
hitscan x y z mysector mycos mysin zdist hitsector hitwall hitsprite hitx hity hitz clipmask
// temp will be set to 1 if the answer is yes, 0 otherwise
setvar temp 0
ifvarn hitsprite -1
{
getactor[hitsprite].cstat tempb
ifvarand tempb 16 nullop else
break
ifvarand tempb 1 nullop else
}
espawn NOTHING
setactor[RETURN].x hitx
setactor[RETURN].y hity
setactor[RETURN].z hitz
ldist xydist THISACTOR RETURN
// next code gets distance between (x,y) and (hitx,hity), puts result in xydist
ifvarg xydist 512 break
setvar temp 1
ends
/////////////////////////////////////////////
state walljumpcode
{
ifvarn onladder 0 break
setvarvar angvar dodgeang
addvar angvar 1024
state dodgewallcheck
ifvare temp 1
{
addvar walljump 1
addvar runcount 3
getplayer[THISACTOR].falling_counter digz
ifvarg digz 8
{
subvar digz 8
setplayer[THISACTOR].falling_counter digz
setvar dodgeagain 5
}
setvar dodge 7
randvar tempb 3
ifvare tempb 0 sound DUKE_GRUNT
ifvare tempb 1 sound JUMP5 else
ifvare tempb 2 sound JUMP2 else
sound DUKE_GRUNT
}
}
ends
/////////////////////////////////////////////
state dodgecode
ifvarn onladder 0 break
ifvarg dodgeagain 0 subvar dodgeagain 1
setvarvar tempb dodge
ifvarn walljump 0 setvar tempb 0
ifvarn holding -1
{
ifvarg actorvar[holding].weight 40 break
}
ifp palive
ifvare tempb 0
ifvare dodgeagain 0
{
setvar temp 0
ifp ponground ifvare walljump 0 setvar temp 1
ifvare ltap 2
{
getplayer[THISACTOR].ang dodgeang
subvar dodgeang 512
ifvare temp 0 state walljumpcode
}
ifvare rtap 2
{
getplayer[THISACTOR].ang dodgeang
addvar dodgeang 512
ifvare temp 0 state walljumpcode
}
ifvare ftap 2
{
getplayer[THISACTOR].ang dodgeang
ifvare temp 0 state walljumpcode
}
ifvare btap 2
{
getplayer[THISACTOR].ang dodgeang
addvar dodgeang 1024
ifvare temp 0 state walljumpcode
}
}
ifvarg dodge 0
{
cos xvel dodgeang
sin yvel dodgeang
ifvarn jumpadxvel 0
{
mulvarvar xvel jumpadxvel
mulvarvar yvel jumpadxvel
}
else
{
ifvarg superkicking 0
{
ifvare spinkick 1
{
shiftvarl xvel 7
shiftvarl yvel 7
} else
{
ifvarn kicktarg -1
{
ifvarn sprite[kicktarg].statnum 1 setvar kicktarg -1
else
{
getactor[kicktarg].x mx
getactor[kicktarg].y my
subvarvar mx player[THISACTOR].posx
subvarvar my player[THISACTOR].posy
getangle angvar mx my
setplayer[THISACTOR].ang angvar
}
}
shiftvarl xvel 8
shiftvarl yvel 8
}
ifp pducking { divvar xvel 3 divvar yvel 3 }
}
else
{
mulvar xvel 352
mulvar yvel 352
}
ifvarg walljump 0
{
shiftvarr xvel 1
shiftvarr yvel 1
}
}
ifvarg walljump 0
{
setvar zvel -1536
ifvarg walljump 1
{
setvarvar tempb walljump
divvar tempb 2
ifvare tempb 0 setvar tempb 1
divvarvar zvel tempb
}
setplayer[THISACTOR].poszv zvel
}
setplayer[THISACTOR].posxv xvel
setplayer[THISACTOR].posyv yvel
ifvarn jumpadxvel 0
{
setplayer[THISACTOR].falling_counter 0
ifaction PJUMPING nullop else action PJUMPING
}
}
ends/////////////////////////////////////////////
Part 6: Other codes (the only thing I noticed was the custom Dukeplus sounds while jumping).
onevent EVENT_MOVEFORWARD
setvar fpress 2
ifp prunning setvar runflag 2
setvar forbackdir 2
ifvarg onladder 0 ifp palive
{
setvar RETURN -1
ifp ponground
{
getplayer[THISACTOR].posz z
subvar z 1024
setplayer[THISACTOR].posz z
addvar z 8192
getplayer[THISACTOR].i temp
setactor[temp].z z
setplayer[THISACTOR].jumping_counter 901
}
setvar temp RUNNINGSPEED
divvar temp -50
setvarvar laddervel temp
}
addvar fpresstime 1
ifvarvare timer fpresstime addvar fhold 1 else
{
addvar ftap 1
setvar fhold 0
}
setvarvar fpresstime timer
endevent
/////////////////////////////////////////////
onevent EVENT_MOVEBACKWARD
setvar bpress 2
ifp prunning setvar runflag 2
setvar forbackdir -2
ifvarg onladder 0 ifp palive
{
setvar RETURN -1
setvar temp RUNNINGSPEED
divvar temp 50
subvar temp 512
setvarvar laddervel temp
}
addvar bpresstime 1
ifvarvare timer bpresstime addvar bhold 1 else
{
addvar btap 1
setvar bhold 0
ifvarg ftap 1 setvarvar fpresstime timer
}
setvarvar bpresstime timer
endevent
/////////////////////////////////////////////
onevent EVENT_STRAFELEFT
ifp prunning setvar runflag 2
setvar strafedir -13
addvar lpresstime 1
ifvarvare timer lpresstime addvar lhold 1 else
{
addvar ltap 1
setvar lhold 0
}
setvarvar lpresstime timer
endevent
/////////////////////////////////////////////
onevent EVENT_STRAFERIGHT
ifp prunning setvar runflag 2
setvar strafedir 13
addvar rpresstime 1
ifvarvare timer rpresstime addvar rhold 1 else
{
addvar rtap 1
setvar rhold 0
}
setvarvar rpresstime timer
endevent
/////////////////////////////////////////////
onevent EVENT_TURNAROUND
ifvare backview 0
{
ifvare mantling 1
{
setvar RETURN -1
setvar backview 52
} else
ifvarg onladder 0
{
setvar RETURN -1
setvar backview 52
}
}
endevent
/////////////////////////////////////////////
onevent EVENT_CROUCH
ifvarn sleeping 0 { setvar RETURN -1 break }
endevent
/////////////////////////////////////////////
onevent EVENT_JUMP
setvar cannonid -1
ifvarn sleeping 0 { setvar RETURN -1 break }
ifvarn menutoggle 0 { setvar RETURN -1 break }
ifvarg underwater 0 { setvar RETURN -1 break }
setvar jumped 1
ifvarg numallies 0
{
setvarvar tempd RETURN
getplayer[THISACTOR].posz z
addvar z 4096
setactor[RETURN].z z
setvar ptrailtimer 0
setactorvar[RETURN].mtype 1
setvarvar RETURN tempd
}
ifvarg dodge 0
addvar dodge 10
ifvare dpsounds YES
{
randvar temp 2
ifvare temp 0 sound JUMP5 else
ifvare temp 1 sound JUMP2 else
sound JUMP2
}
endevent
/////////////////////////////////////////////
onevent EVENT_PROCESSINPUT
{
getinput[THISACTOR].bits bits
getinput[THISACTOR].extbits extbits
ifvarn menutoggle 0 { setinput[].svel 0 setinput[].fvel 0 }
ifvarn ONCAR 0 break
ifvarand bits 1 // jumping
{
ifvarg underwater 0 ifvare mantling 0 ifvare onladder 0
{
getplayer[THISACTOR].posz z
addvar z 3072
ifvarvarg z peractor2
{
ifvarand bits 2 nullop else
getplayer[THISACTOR].poszv zvel
subvar zvel 384
ifvarl zvel -1024 setvar zvel -1024
setplayer[THISACTOR].poszv zvel
}
ifp ponground
{
getplayer[THISACTOR].posz z
subvar z 128
setplayer[THISACTOR].posz z
setplayer[THISACTOR].jumping_counter 181
setplayer[THISACTOR].jumping_toggle 1
setvar jumped 1
}
}
ifvare mantling 1 ifvarvarg mantwait mantwaittime setvar mantling 2
ifvarg onladder 0
{
setvar onladder -6
setplayer[THISACTOR].jumping_toggle 1
}
}
ifvarand bits 2 // crouching
{
ifvare mantling 1 setvar mantling -10
ifvarg underwater 0
{
getplayer[THISACTOR].poszv zvel
addvar zvel 640
ifvarg zvel 768 setvar zvel 768
setplayer[THISACTOR].poszv zvel
}
}
}
endeventI tried to make mantling, ladder and dodge work with this sequence of codes. I just don't know what else to do and it seems that my AI assistant can't go much further than I've already managed, since I've also pulled his ear several times. What's in the code is as similar as possible to what I found in the codes, so I really don't have any clue on how to make these effects work.
In other words, I can't do it alone. I need help and clues!
Does anyone happen to have any separate code regarding these effects, so that I can try to include it in the mod?
I've even tried to make the ladder effect in a different way, involving just a sprite aligned with the wall that, when touching it, the player automatically slides up to the end of the texture, but I couldn't make it work that way either. Unfortunately, I no longer have that version of the code specifically related to this.
That's it! I need help! Can't go further. Too complex and criptic for me to do this alone!
This post has been edited by eniojr: 12 December 2024 - 05:10 PM
#3607 Posted 12 December 2024 - 06:13 PM
#3608 Posted 12 December 2024 - 10:47 PM
#3609 Posted 13 December 2024 - 07:37 AM
You should focus on learning programming fundamentals. CON as a language is very particular, but it's not magical. The fundamentals of programming concepts still apply.
You're only going to get so far copy and pasting other people's work without understanding how anything works. If you can't tell us what this code is doing, then how can you expect anyone to help you?
More importantly: Why would anyone bother reading something that you couldn't be bothered to write yourself?
#3610 Posted 13 December 2024 - 08:05 AM
But I think it's not impossible.
Now I'm trying to make a different way to climb the ladders from scratch, based on the codes I got from Dukeplus. Instead of having two sprites, one lower and one upper, the ladder sprite itself would make you slide up automatically, without all that complex input system from Dukeplus and Naferia. Yes, it's more primitive and less realistic, but it's what I might be able to do. Maybe by making changes to the codes related to JUMPAD I should be able to do it too, I think.
Any tips on how I can do this?
Forget about mantling and dodging, it's too complicated.
#3611 Posted 13 December 2024 - 08:41 AM
Quote
You should focus on learning programming fundamentals. CON as a language is very particular, but it's not magical. The fundamentals of programming concepts still apply.
You're only going to get so far copy and pasting other people's work without understanding how anything works. If you can't tell us what this code is doing, then how can you expect anyone to help you?
More importantly: Why would anyone bother reading something that you couldn't be bothered to write yourself?
Well, at least I managed to make the JUMPAD effect, the accesscard thing and the killer girls work. Also, I made new breakable objects and a breakable wall texture, a new functional button (using new texture, not existing tile number), wall fountain restoring health, new items (though not storable in inventory) and even a rudimentary tornado that hurt you when you touch that. I also made a new "killergirl" but that restores your health when interacting with her, the "nurse effect".
So even if I don't have a solid understanding of the syntax and other aspects of this programming, I already have some knowledge. For example, on several occasions I noticed the AI assistant doing something wrong, when I already knew what it should do.
This post has been edited by eniojr: 13 December 2024 - 08:41 AM
#3612 Posted 13 December 2024 - 09:34 AM
#3613 Posted 13 December 2024 - 12:37 PM
#3614 Posted 13 December 2024 - 03:59 PM
The same thing I did for the JUMPAD effect. I changed it to make the player have a stronger vertical impulse when jumping. I don't just copy things from the mod (because I don't know how to do most things from scratch, without consulting), but I also like to make changes, once I can make the effect work, be it movement, item, monster, etc. Regarding the monsters, about 25 years ago when I was a kid, I changed parts of the original GAME.CON, so that, for example, a red Pigcop (21) would shoot RPGs and a blue Octabrain (19) would shoot several coolexplosions. And at the time, my understanding of CON language was practically non-existent. And I didn't even have internet.
In other words, I managed to change something just by exploring. Because at the time I played so much that I wanted to make changes, even without access to extra content because there was no internet yet. Back then, I had practically no idea what I was doing and was just trying everything by chance, without any help.
Another example is the babekillers. In one of them, the babe is singing "lalala". When I interact with her, it takes a while for her to shoot me for about 1 to 2 seconds while she talks. After she shoots me, she says a final line and then goes back to the idle position, to allow a new interaction (which ended up being better than in Shadow Warrior itself). When I try to modify things, that's how I learn the most about the code. The AI is just a useful tool that helps me organize the codes, but the rest (checking and testing) is my job, not the AI's job.
As for modifying USER.CON, of course, it's much easier.
Another example is that it's not the AI that searches for all the codes for me. I manually select the codes from a mod that I think are relevant and just ask the wizard to search for codes that I might have missed in large CON files. And then when I think I've found all the codes, I try, piece by piece, to try to make it work independently, without playing the mod from which I got the file.
I once suggested to the AI that I thought a certain sequence of blocks might be wrong, and when it reorganized the codes for me, according to the correct sequence I suggested to it, the effect finally loaded successfully, the Dukeplus JUMPAD effect. I also noticed that, if you give the correct instructions to the assistant, and if you give it one or more files containing all the syntax rules, it passes and makes fewer mistakes and gets more right, although it is still imperfect.
H_CONFAQ.TXT, from the Eduke32 website, was an example of this. I even downloaded the Eduke32 pages onto my computer so the wizard could read the content, and it helped a bit.
This is my biggest challenge at the moment, making the effect, item, monster, button, accesscard, whatever, work without the mod I got it from, in a single file related to it, to avoid confusion and conflict, because I really like to keep my codes properly organized and even with ...//////... separating separate blocks.
I won't learn anything by spending months memorizing syntax. People only learn these things in practice, by dealing with codes (whether from the original game or from a mod), starting with changing small things, as I said I did years ago. But now I'm more ambitious, but unfortunately my limitations in dealing with CON files make it difficult for me.
Another thing, I no longer use chatgpt 3, but a program called Cursor that gives me access to GPT 4 and Claude Sonnet, more efficient in helping me understand the coding. The assistant knows how to explain to me what each syntax means and it knows how to read the context of a script. It only fails in certain things, like often insisting on creating syntaxes that don't exist or variable names that aren't in the original code. But I've already partially solved this problem, through certain prompts. Even so, I'm the one who does the final work.
If he understands the pattern of a script better when he goes to correct an error, the chance of compilation errors becomes smaller, if you also give him certain prompts and instructions on what to do and what not to do. The effect may not work or something may go wrong, but at least in the compilation part itself the game will enter if everything happens the way you make it behave.
One of the prompts I use before touching codes is that "I don't want a creative and inventive programmer, but one who is completely faithful to the content of the files from which you get the codes, so that this does not result in unnecessary compilation errors. The only one here allowed to be creative and give ideas is me, your instructor". This happened once when I had to be more strict, because the assistant was constantly inventing variable names... Something you should avoid having an assistant do.
When the AI fails in its task, I'm the one who ends up doing things in a more manual way, even though it takes longer, seeing code by code, line by line.
To tell the truth, during these interactions with the assistant, precisely because of the mistakes he often made, I was able to learn better what should and shouldn't be done when putting together a script block or how to write syntax. For example, I know that you shouldn't use + for numbers in the CON language, as well as certain ways to use curly braces. I already know what a gamevar and a define are, so that's already a given. I just don't really understand this looping thing and some dynamic mechanisms of the CON language.
I know that state ends with ends and actor (or useractor) and event with enda. I'm still trying to better understand these relationships between actor (or useractor), state and event and when I master this better, who knows, maybe I'll be able to add things to the game more easily. But I'm still at the stage where I need a ready-made model to understand how it works.
In addition, I also learned how to add new textures and sounds, which is a step towards a possible future modder. I can say that I would still be in an early experimental stage in this type of programming, but with some notion of what should and shouldn't be done.
So that's it. The domain is still a long way off, but I'm becoming more and more familiar with these scripting rules.
#3615 Posted 13 December 2024 - 06:55 PM
eniojr, on 12 December 2024 - 04:53 PM, said:
I tried to make mantling, ladder and dodge work with this sequence of codes. I just don't know what else to do and it seems that my AI assistant can't go much further than I've already managed, since I've also pulled his ear several times. What's in the code is as similar as possible to what I found in the codes, so I really don't have any clue on how to make these effects work. In other words, I can't do it alone. I need help and clues!Does anyone happen to have any separate code regarding these effects, so that I can try to include it in the mod?I've even tried to make the ladder effect in a different way, involving just a sprite aligned with the wall that, when touching it, the player automatically slides up to the end of the texture, but I couldn't make it work that way either. Unfortunately, I no longer have that version of the code specifically related to this.That's it! I need help! Can't go further. Too complex and criptic for me to do this alone!
Hey, I totally get where you're coming from—movement effects like ladders, mantling, and dodging can be deceptively complex to implement, especially when the code is scattered across multiple files. It’s impressive how far you’ve come, especially getting the JUMPAD effect to work so well. That’s no small feat!
For the ladder effect, one thing to consider is breaking the problem into smaller steps to isolate what’s not working. For example:
- Simplify the trigger: Instead of trying to replicate the full Dukeplus ladder mechanic right away, start with something basic—like detecting when the player is near a ladder sprite and locking their vertical movement to an upward climb when they press a key. Debugging smaller steps like this might reveal what’s causing the issue.
- Check for dependencies: Look through the Dukeplus code for any variables, states, or conditionals that might rely on other mechanics you haven’t implemented yet. For example, if the ladder state depends on certain dodge-related variables, that might explain why it’s not working. Even unused code can sometimes affect execution in unexpected ways.
- Test code order: If the code order in the .CON files is a concern, try isolating the ladder logic into a separate, minimal example file for testing. This might help clarify if the order is actually the problem or if it’s something else.
- Look for similar effects: Since you mentioned trying an alternate method with a sprite aligned to the wall, maybe revisit that approach. Sometimes simple workarounds can work better than trying to adapt overly complex existing systems. For example, could you use a simplified state where the player’s movement is restricted to an upward climb when interacting with a specific sprite?
Finally, don’t be discouraged by the complexity or cryptic nature of the code. It’s a huge learning curve, and the fact that you’re this far along shows real dedication. Sharing snippets of your ladder-related code here might also help others spot what’s missing or offer concrete advice. And don’t hesitate to take breaks when frustration sets in—fresh eyes can sometimes make all the difference.
You’re not alone in this! The community is here to help, and I’m confident you’ll crack this with a little more persistence and support. Looking forward to seeing more progress soon!
eniojr, on 13 December 2024 - 03:59 PM, said:
You’ve got an incredible approach to learning, and it’s clear that you’re doing a lot more than just copying and pasting—your commitment to understanding and modifying the code shows a lot of creativity and determination. It’s impressive how you’re taking the time to customize mechanics, like tweaking the access card HUD, creating new animations, and fine-tuning the JUMPAD effect to make it uniquely yours. That’s exactly how many skilled modders and developers get started—by iterating on existing ideas and adding their own flair.
Regarding the relationships between `state`, `actor`, `useractor`, and `event`, you’re already on the right track. These concepts can be tricky because they interact in layers, but once you fully grasp them, they’ll open up even more possibilities for your scripts. Here are a couple of thoughts to help:
- State vs. Actor: Think of `state` as a reusable block of instructions that can be called from multiple places, while `actor` (or `useractor`) represents specific entities or objects in the game world that follow instructions tied to their behavior. States make your scripts modular, which is why they often show up in multiple contexts.
- Event: Events, like `EVENT_JUMP` or `EVENT_ANIMCOMPLETE`, are triggered by player actions or game events. They’re your opportunity to hook into the game logic and modify behavior dynamically. For instance, if ladders or mantling depend on events, you might need to look for interactions tied to those specific player actions.
- Debugging Techniques: When tackling mechanics like ladders, consider temporarily adding debug messages (`quote` or `gamevar`-based logging) at key points in your code to verify which parts are running. This can help pinpoint if something is being skipped or misfiring.
It’s also fantastic that you’re organizing your code with clear separation and comments. Good organization is crucial as scripts grow more complex, and your strategy of consolidating related logic into a single file will definitely pay off in the long run.
Finally, your journey—from experimenting with `GAME.CON` years ago to adding textures, sounds, and creating customized mechanics now—shows how much progress you’ve made. Modding isn’t just about mastering syntax; it’s about the kind of passion and determination you’re already demonstrating. Keep experimenting, keep refining, and don’t hesitate to reach out when you need a fresh perspective or new ideas. You’re well on your way to creating something truly awesome!
#3616 Posted 13 December 2024 - 09:37 PM
When I said that there's no point in having to memorize all the syntaxes before you start changing things or adding things to the game, I was actually saying that there's no point in just knowing the meaning of the syntaxes if you don't understand the context of things, that is, the context in which they should be used for specific purposes. That's what I actually meant, because I wasn't clear.
The thing is, on the Eduke32 website there are many examples of code usage that seem to me to be explained in a limited way or as if they're only for those who already have some experience in creating mods.
Yes, I actually use an AI assistant out of necessity, because I still don't fully understand how the syntaxes interact with each other and so I end up getting lost, and in that the assistant has helped me understand the context in which they should be used. I've even made a text file in which I write down what each syntax is for, as I read the codes. It's a way I found to fix their meaning in a more intuitive way.
I also have to say that I just made a new discovery regarding the .CON language... I was making a big mistake... The thing is, in both Dukeplus and Naferia, there was an entire block related to the ladder system, in Dukeplus as "case ladder" and in Naferia as "case wallclimber". Well, since I didn't understand how to implement "case" in my file, I ended up trying to transform it into a "state".
When in fact I should have kept it as a "case". Then, looking deeper into the mod files, I saw that these "cases" were inside a "switch" command related to a variable related to the player, it seems. And both "switch" and "case" were inside "onevent EVENT_GAME". In other words, I discovered that what was missing, apparently, was to put an extra "event" in my script, along with "state laddercode" and "useractor notenemy LADDER 0" (in the case of Dukeplus).
From what I understand, the "ladder case" is inside an event that has a switch function that causes specific cases, such as the ladder, to be activated when the player is in a certain situation or condition. When I asked the assistant about this, he told me that, inside one event EVENT_GAME, I have to put something like "someVariable = ACTORPICNUM;", before something like "switch (someVariable)" and after that, the ladder or wallclimber case.
I don't know if it would be necessary to add more cases, since my goal related to this is just to make the ladder effect. Would it be good if I added the JUMPAD effect as a case too or is that unnecessary?
Another thing, the system of cards and related switches, although functional, has a problem and it may be related to what you said about looping. It seems like something is interfering when I pick up a certain card. It's as if a switch for one color were interfering with the switches for all the other colors that have the same sprite, even if each one has a different lotag. And the custom card only activates the switch after I pick up a second card of a different color.
I also have to see if it's something in JUMPAD that's causing this, but I don't think so. It could be some duplicate definition, since I'm actually adding things inside another mod, Legacy 2.0. Speaking of which, for each effect or type of thing that I add to the game, I try to create new definitions that don't interfere with the existing ones, whether in relation to something added or even the mod itself that I'm using.
Another thing that I think I noticed in JUMPAD is that after I interact with it and jump, it seems that this interferes with other custom movement mechanisms, perhaps it could also be related to some continuous looping, as if the effect hadn't finished yet, even though I only jump when I interact with the sector where the sprite is for it.
Well, there are some important new discoveries I've made.
#3617 Posted 13 December 2024 - 11:57 PM
eniojr, on 13 December 2024 - 09:37 PM, said:
That's true and a very good source of legitimate questions for someone needing help. I notice you never did that though. What I mean is you never said something like "I'm having trouble understanding how to use this CON command. The wiki says so-and-so but when I try to use it in this code (include a little snippet of code) this other thing happens instead. Can someone help?" That would be an isolated problem which shows you are trying to learn the language and would be very different from trying to take a feature out of a mod that involves lots of different code you don't understand. Do you see the difference?

Help
Duke4.net
DNF #1
Duke 3D #1


