Handy guides on how to do things, written by users for users.
Forum rules
Please don't start threads here asking for help. This forum is not for requesting guides, only for posting them. If you need help, the Editing forum is for you.
Here's a guide that no one asked for, but hopefully can prove helpful to someone trying something that can easily turn into a not-exactly-flying spaghetti monster without sufficient planning.
Your weapon controls allow up to 8 buttons. This is quite a lot, but sometimes you want to accomplish things through specific combinations of buttons - without getting trapped in a maze of A_(Clear)Refire hacks trying to trace a unique path for every possibility.
Examples:
Dual-wield (or double-barreled, double-triggered) weapons: each of the two fire buttons handles one weapon, and each weapon (which is on a different overlay from the other, of course) can be fired totally independently of what the other is doing - even if the other fire button is still being held down.
Heavy Weapon Guy-style gun spinup: hold altfire to keep your gun ready to fire at any time.
Slam fire shotgun: hold trigger down, hold altfire to rack the shotgun, gun immediately goes off once you chamber the new round.
Panic shot: shoot in the middle of a reload sequence, spending whatever happens to be in the chamber already.
Check for holding Zoom/Reload/other non-A_Refire-able inputs outside of a ready state.
Daggerfall-style melee weapons: hold button, move mouse in the direction to swing.
Wacky weapon with a "jamming typewriter" interface that prevents the weapon from operating if you mash the buttons too fast.
Spellcasting decision trees.
You're a bloody maniac, or extremely undisciplined and disorganized, and have actually run out of buttons for calling all the various weapon functions you have coded.
I've developed some shortcuts that massively improve my own quality of life while trying to do stuff like this. It occurs to me that my setup is not self-evident and might be good to share.
(Yes, what I'm doing here goes against the warning in the performance note here, but given you're not going to be dealing with more than 8 players at any given moment this is relatively trivial.)
class ComboFriendlyWeapon : Weapon { /* Here are some flag groups for A_WeaponReady.
The first by default enables all weapon keys at once, letting you do everything.
The second disables all buttons and deselect, leaving only the weapon bobbing (assuming the player has enabled it). This allows you to have a "fake" ready state in which you are actually directly checking input instead of the native ready code, or adding a long static frame that would look really awkward if frozen while the player walks. */ enum ComboWeaponConstants { WRF_ALL = WRF_ALLOWRELOAD|WRF_ALLOWZOOM| WRF_ALLOWUSER1|WRF_ALLOWUSER2| WRF_ALLOWUSER3|WRF_ALLOWUSER4, WRF_NONE = WRF_NOFIRE|WRF_DISABLESWITCH, }
/* A wrapper for SetPSprite. Basically SetStateLabel for weapon overlays.
I'm not sure if the player null pointer check is necessary... */ action void SetWeaponState(statelabel st,int layer=PSP_WEAPON) { if(player) player.setpsprite(layer,invoker.findstate(st)); }
/* These are shortcuts for checking player input.
Obviously you can just type out the whole thing, but if you're in the middle of typing out lots of different potential combos you will have plenty enough to keep track of without trying to remember exactly what that long string is that you need to get in order to do the check. */ action bool PressingFire(){return player.cmd.buttons & BT_ATTACK;} action bool PressingAltfire(){return player.cmd.buttons & BT_ALTATTACK;} action bool PressingReload(){return player.cmd.buttons & BT_RELOAD;} action bool PressingZoom(){return player.cmd.buttons & BT_ZOOM;} action bool PressingUser1(){return player.cmd.buttons & BT_USER1;} action bool PressingUser2(){return player.cmd.buttons & BT_USER2;} action bool PressingUser3(){return player.cmd.buttons & BT_USER3;} action bool PressingUser4(){return player.cmd.buttons & BT_USER4;} /* EDIT: Have a couple more: */ action bool PressingUse(){return player.cmd.buttons & BT_USE;} action bool JustPressed(int which)// "which" being any BT_* value, mentioned above or not { return player.cmd.buttons & which &&!(player.oldbuttons & which); } action bool JustReleased(int which) { return !(player.cmd.buttons & which)&& player.oldbuttons & which; }
/* You can set up these shortcuts for any player input, and any arbitrary combination thereof: "TurnSpeed", "ForwardMove", "CrouchRunning", etc. etc. etc., and you can of course add new variables to the weapon to keep track of certain states at certain times...
(I don't actually use these examples below, as these situations don't come up in HD enough to call for them, but some of my bullet point examples can use them.) */ action double TurnSpeed() { return((double(player.cmd.pitch),double(player.cmd.yaw)).length()); } double LastCheckedTurnSpeed;
class ComboSSG : ComboFriendlyWeapon { states { ready: SHT2 A 1 { /* If you press Fire, the weapon will flash in the FireLeft state on layer number 1000. Presumably this will consist of a flash of the left barrel and code to fire the appropriate bullets and deplete the appropriate ammo. */ if(PressingFire()) SetWeaponState("fireleft", PSP_FLASH);
/* Same thing with Altfire and FireRight. Note that there is NOT an "else" here - if you hit both buttons both barrels will go off. This is why it's important to make sure these flashes are in different layers.
This might look really bad depending on how your flash sprites are made. In that case you might want to have a third condition at the very start of this function that checks for both buttons and returns if the result would have both barrels going off at exactly the same time, e.g.:
if(PressingFire() && PressingAltfire()) { SetWeaponState("fireboth", PSP_FLASH); return; } */ if(PressingAltfire()) SetWeaponState("fireright", PSP_FLASH2); A_WeaponReady(WRF_NOFIRE);//not "none" as we still want to deselect }loop; } enum SSGNums { //you could just type "999" right in the ready state, //but you could regret that later. PSP_FLASH2 = 999, } }
Last edited by Matt on Tue Oct 16, 2018 3:37 pm, edited 7 times in total.