ungeneric method var restore, akimbo cleanup and ejectshell type setup

This commit is contained in:
Chris Dawalt 2021-08-09 05:43:03 -04:00
parent 3b37190955
commit a0a70e7c9e
29 changed files with 622 additions and 570 deletions

View file

@ -14,6 +14,7 @@
// NEW. When present, the origin is exactly at the center of the player, no further offsets.
// Keeps the view identical on the player dying and becoming spectator in place.
// Requires some hack-ins to Nuclide in order to work, but hey, it is a debug feature
//#define DEBUG_FORCE_NO_VIEW_OFFSET

View file

@ -99,7 +99,7 @@ UI_ChangeScreen(UI_SCREEN arg_NewScreenID)
printfline("UI_ChangeScreen:: arg_NewScreenID? %d", arg_NewScreenID);
if(arg_NewScreenID == UI_SCREEN::NONE){
// If at NONE or below, also do nothing. This has no "vOnInit" behavior.
// If at NONE or below, also do nothing. This has no "funInit" behavior.
// Besides obligatory cleanup if we choose (which may as well be done right here)
// And turn the cursor lock off.
setcursormode(FALSE, "gfx/cursor", [0,0,0], 1.0f);
@ -117,7 +117,7 @@ UI_ChangeScreen(UI_SCREEN arg_NewScreenID)
return;
}
// If this screen has a vOnInit, do it!
// If this screen has a funInit, do it!
// This is done for the new screen once as soon as it becomes the active one.
// Also, turn the cursor lock on, clearly this needs user input.
// src/client/entry.qc already has this check too for having any UI widget, but
@ -327,7 +327,7 @@ UI_Draw(void)
{
if ( pSeatLocal->m_flUI_Display == UI_SCREEN::NONE ) {
setcursormode( FALSE );
return FALSE;
return;
}
if(g_UI_queueInit){
@ -337,7 +337,7 @@ UI_Draw(void)
if(!ary_UI_Screen[pSeatLocal->m_flUI_Display-1].bInitializedYet){
// no drawing uninitialized UI. Is this even possible?
return FALSE;
return;
}
UI_determineDrawGlobals();
@ -354,7 +354,7 @@ UI_Draw(void)
// Display the contents of whatever we have selected
ary_UI_Screen[pSeatLocal->m_flUI_Display-1].funDraw();
return TRUE;
return;
}

View file

@ -15,18 +15,18 @@
#define INITIALIZE_BASICBUTTON(arg_varName, arg_sName, arg_sHotkeyDisplay, arg_clr, arg_vOnClick_Custom) buymenu_btn_##arg_varName = spawn(CBuyMenu_BasicButton);\
#define INITIALIZE_BASICBUTTON(arg_varName, arg_sName, arg_sHotkeyDisplay, arg_clr, arg_funOnClick_Custom) buymenu_btn_##arg_varName = spawn(CBuyMenu_BasicButton);\
flDeterminedHotkey = determineHotkeyFromChar(arg_sHotkeyDisplay);\
buymenu_btn_##arg_varName.setThisPointer(&buymenu_btn_##arg_varName);\
buymenu_btn_##arg_varName.create(sprintf("%s %s", arg_sHotkeyDisplay, arg_sName), flDeterminedHotkey, arg_clr, arg_vOnClick_Custom);\
buymenu_btn_##arg_varName.create(sprintf("%s %s", arg_sHotkeyDisplay, arg_sName), flDeterminedHotkey, arg_clr, arg_funOnClick_Custom);\
buymenu_addbuttonToTotal(&buymenu_btn_##arg_varName);
#define INITIALIZE_WEAPONBUTTON(arg_varName, arg_sHotkeyDisplay, arg_clr, arg_vOnClick_Custom, arg_parentName) buymenu_btn_Buy_##arg_varName = spawn(CBuyMenu_WeaponButton);\
#define INITIALIZE_WEAPONBUTTON(arg_varName, arg_sHotkeyDisplay, arg_clr, arg_parentName) buymenu_btn_Buy_##arg_varName = spawn(CBuyMenu_WeaponButton);\
flDeterminedHotkey = determineHotkeyFromChar(arg_sHotkeyDisplay);\
buymenu_btn_Buy_##arg_varName.setThisPointer(&buymenu_btn_Buy_##arg_varName);\
tempWeapRef = *ary_weaponData[WEAPON_ID::##arg_varName];\
buymenu_btn_Buy_##arg_varName.create_WeaponButton(sprintf("%s %s", arg_sHotkeyDisplay, tempWeapRef.sDisplayName), flDeterminedHotkey, arg_clr, arg_vOnClick_Custom, tempWeapRef.sIconFilePath, tempWeapRef.iPrice, tempWeapRef.iSlots, tempWeapRef.iBitsUpgrade & ~tempWeapRef.iBitsUpgradeAuto);\
buymenu_btn_Buy_##arg_varName.create_WeaponButton(sprintf("%s %s", arg_sHotkeyDisplay, tempWeapRef.sDisplayName), flDeterminedHotkey, arg_clr, NULL, tempWeapRef.sIconFilePath, tempWeapRef.iPrice, tempWeapRef.iSlots, tempWeapRef.iBitsUpgrade & ~tempWeapRef.iBitsUpgradeAuto);\
buymenu_addbuttonToTotal(&buymenu_btn_Buy_##arg_varName);\
buymenu_btn_Buy_##arg_varName.iWeaponPurchaseID = WEAPON_ID::##arg_varName;\
buymenu_addbutton(&buymenu_btn_Buy_##arg_parentName, &buymenu_btn_Buy_##arg_varName);
@ -201,22 +201,22 @@ class CBuyMenu_BasicButton{
// Special behavior for this button (optional). Good for buttons that will interact
// with something in the game like adding a weapon or adding an accessory (Silencer) to an existing one.
//virtual void(CBuyMenu_BasicButton* arg_this) vOnClick_Custom = NULL;
int* vOnClick_Custom;
//virtual void(CBuyMenu_BasicButton* arg_this) vOnShow_Custom = NULL;
int* vOnShow_Custom;
virtual void(CBuyMenu_BasicButton* arg_this) funOnClick_Custom = NULL;
//int* funOnClick_Custom;
virtual void(CBuyMenu_BasicButton* arg_this) funOnShow_Custom = NULL;
//int* funOnShow_Custom;
void(void) CBuyMenu_BasicButton;
virtual void(CBuyMenu_BasicButton* arg_this) setThisPointer;
virtual void(string arg_sName, float arg_flHotkey, vector arg_clr, void(CBuyMenu_BasicButton* arg_this)* arg_vOnClick_Custom ) create;
virtual void(string arg_sName, float arg_flHotkey, vector arg_clr, void(CBuyMenu_BasicButton* arg_this) arg_funOnClick_Custom ) create;
virtual void(vector arg_suggestedDrawPos, int arg_iLayer, int arg_iButtonRow, BOOL arg_fIsSelected) vOnRender_Base;
virtual void(void) vOnClick_Base;
virtual void(vector arg_suggestedDrawPos, int arg_iLayer, int arg_iButtonRow, BOOL arg_fIsSelected) funOnRender_Base;
virtual void(void) funOnClick_Base;
virtual void(void) vOnShow_Base;
virtual void(void) funOnShow_Base;
// This is set separately from any "create" methods or constructors since it is rarely used.
// If set, this method will run anytime this button is shown. This lets it do a quick calculation
@ -243,14 +243,13 @@ class CBuyMenu_WeaponButton : CBuyMenu_BasicButton{
void(void) CBuyMenu_WeaponButton;
// after arg_clr: int arg_ary_btn_index[16]
virtual void(string arg_sName, float arg_flHotkey, vector arg_clr, void(CBuyMenu_BasicButton* arg_this)* arg_vOnClick_Custom, string arg_sWeaponImagePath, int arg_iWeaponPrice, int arg_iWeaponSlots, int arg_iBitsWeaponOpt ) create_WeaponButton;
virtual void(string arg_sName, float arg_flHotkey, vector arg_clr, void(CBuyMenu_BasicButton* arg_this) arg_funOnClick_Custom, string arg_sWeaponImagePath, int arg_iWeaponPrice, int arg_iWeaponSlots, int arg_iBitsWeaponOpt ) create_WeaponButton;
virtual void(vector arg_suggestedDrawPos, int arg_iLayer, int arg_iButtonRow, BOOL arg_fIsSelected) vOnRender_Base;
virtual void(void) vOnClick_Base;
virtual void(vector arg_suggestedDrawPos, int arg_iLayer, int arg_iButtonRow, BOOL arg_fIsSelected) funOnRender_Base;
virtual void(void) funOnClick_Base;
virtual void(void) vOnShow_Base;
//virtual void(CBuyMenu_BasicButton* arg_this) vOnShow_Custom = NULL;
virtual void(void) funOnShow_Base;
};
@ -282,11 +281,11 @@ checkBuyMenuButtonClicked(
{
CBuyMenu_BasicButton deref = *arg_someBtn;
if(UI_CheckMouse( vPosition, vSize )){
if(UI_CheckMouse(vPosition, vSize)){
// What button is being hovered over?
iHoveredButtonIndex = deref.iGlobalIndex;
(*arg_someBtn).vOnClick_Base();
(*arg_someBtn).funOnClick_Base();
pSeatLocal->m_inputMouseClicked = FALSE;
return TRUE;
@ -305,7 +304,7 @@ checkBuyMenuButtonHotKeyPressed(
// Check for the button's hotkey.
if(deref.flHotkey != -1 && pSeatLocal->m_inputKeyDown == deref.flHotkey){
(*arg_someBtn).vOnClick_Base();
(*arg_someBtn).funOnClick_Base();
pSeatLocal->m_inputKeyDown = 0;
return TRUE;
}
@ -550,8 +549,8 @@ CBuyMenu_BasicButton::CBuyMenu_BasicButton(void)
{
iType = BUTTON_TYPEID_BASIC;
bActive = TRUE;
vOnClick_Custom = NULL;
vOnShow_Custom = NULL;
funOnClick_Custom = NULL;
funOnShow_Custom = NULL;
}
void
CBuyMenu_BasicButton::setThisPointer(CBuyMenu_BasicButton* arg_this)
@ -559,46 +558,48 @@ CBuyMenu_BasicButton::setThisPointer(CBuyMenu_BasicButton* arg_this)
_this = arg_this;
}
void
CBuyMenu_BasicButton::create(string arg_sName, float arg_flHotkey, vector arg_clr, void(CBuyMenu_BasicButton* arg_this)* arg_vOnClick_Custom )
{
CBuyMenu_BasicButton::create(
string arg_sName, float arg_flHotkey, vector arg_clr,
void(CBuyMenu_BasicButton* arg_this) arg_funOnClick_Custom
){
sName = arg_sName;
flHotkey = arg_flHotkey;
clr = arg_clr;
clr_render = arg_clr; //good default.
vOnClick_Custom = arg_vOnClick_Custom; //(int*)&arg_vOnClick_Custom;
vOnShow_Custom = NULL;
funOnClick_Custom = arg_funOnClick_Custom; //(int*)&arg_funOnClick_Custom;
funOnShow_Custom = NULL;
}//create
void
CBuyMenu_BasicButton::vOnRender_Base
CBuyMenu_BasicButton::funOnRender_Base
(
vector arg_suggestedDrawPos, int arg_iLayer, int arg_iButtonRow, BOOL arg_fIsSelected
)
{
drawBuyButton(this.iGlobalIndex, this.sName, arg_suggestedDrawPos, arg_iLayer, arg_iButtonRow, arg_fIsSelected, this.clr_render);
}//vOnRender_Base
}//funOnRender_Base
void
CBuyMenu_BasicButton::vOnShow_Base(void)
CBuyMenu_BasicButton::funOnShow_Base(void)
{
if(vOnShow_Custom != NULL){
void(CBuyMenu_BasicButton* arg_this)* tempRef = vOnShow_Custom;
(*tempRef)(_this);
//vOnShow_Custom(_this);
if(funOnShow_Custom != NULL){
//void(CBuyMenu_BasicButton* arg_this)* tempRef = funOnShow_Custom;
//(*tempRef)(_this);
funOnShow_Custom(_this);
}
}// vOnShow_Base
}// funOnShow_Base
// When this button is clicked, what does it do?
void
CBuyMenu_BasicButton::vOnClick_Base(void)
CBuyMenu_BasicButton::funOnClick_Base(void)
{
// basic button behavior. Only if our array has a non-zero length.
@ -620,7 +621,7 @@ CBuyMenu_BasicButton::vOnClick_Base(void)
// Also: go through each button that I'm going to show and set its "bAtive" to TRUE
// (all buttons like weapon upgrades are visible
// unless purchased in that showing of the weapon). And call each one's "vOnShow"
// unless purchased in that showing of the weapon). And call each one's "funOnShow"
// since there may be some logic such as
// coloring the text red if the player can't afford that upgrade or weapon (in the
// case of entire weapons by name buttons too).
@ -630,27 +631,27 @@ CBuyMenu_BasicButton::vOnClick_Base(void)
if(someButton.iType == BUTTON_TYPEID_WEAPON){
CBuyMenu_WeaponButton someButto = *((CBuyMenu_WeaponButton*)ary_btnTotal[nextButtonIndex]);
someButto.bActive = TRUE;
someButto.vOnShow_Base();
someButto.funOnShow_Base();
}else{
someButton.bActive = TRUE;
someButton.vOnShow_Base();
someButton.funOnShow_Base();
}
}
}// button length check
if(vOnClick_Custom != NULL){
if(funOnClick_Custom != NULL){
// If we have a custom click method, do it.
void(CBuyMenu_BasicButton* arg_this)* tempRef = vOnClick_Custom;
(*tempRef)(_this);
//vOnClick_Custom(_this);
//void(CBuyMenu_BasicButton* arg_this)* tempRef = funOnClick_Custom;
//(*tempRef)(_this);
funOnClick_Custom(_this);
}
//Regardless, most buttons are bound to change the current layer and
//possibly what the Cancel/Go Back button says (one of those two).
buymenu_btn_Back_updateText();
}//vOnClick_Base
}//funOnClick_Base
void
@ -664,11 +665,10 @@ void
CBuyMenu_WeaponButton::create_WeaponButton
(
string arg_sName, float arg_flHotkey, vector arg_clr,
void(CBuyMenu_BasicButton* arg_this)* arg_vOnClick_Custom,
void(CBuyMenu_BasicButton* arg_this) arg_funOnClick_Custom,
string arg_sWeaponImagePath, int arg_iWeaponPrice, int arg_iWeaponSlots,
int arg_iBitsWeaponOpt
)
{
){
//defaults.
//_this_deref.iLayer = 0i;
@ -681,8 +681,8 @@ CBuyMenu_WeaponButton::create_WeaponButton
clr = arg_clr;
clr_render = arg_clr; //good default.
vOnClick_Custom = arg_vOnClick_Custom; //(int*)&arg_vOnClick_Custom;
vOnShow_Custom = NULL; //paranoia?
funOnClick_Custom = arg_funOnClick_Custom; //(int*)&arg_funOnClick_Custom;
funOnShow_Custom = NULL; //paranoia?
// Why do we add "_0.tga" to a .spr reference for the draw to work?
// The world may never know.
@ -727,13 +727,13 @@ CBuyMenu_WeaponButton::create_WeaponButton
void
CBuyMenu_WeaponButton::vOnRender_Base
CBuyMenu_WeaponButton::funOnRender_Base
(
vector arg_suggestedDrawPos, int arg_iLayer, int arg_iButtonRow,
BOOL arg_fIsSelected
)
{
CBuyMenu_BasicButton::vOnRender_Base(
CBuyMenu_BasicButton::funOnRender_Base(
arg_suggestedDrawPos, arg_iLayer, arg_iButtonRow, arg_fIsSelected
); //call the parent's.
@ -766,7 +766,7 @@ CBuyMenu_WeaponButton::vOnRender_Base
Gfx_Text( [textDrawOrigin.x, textDrawOrigin.y + (vButtonSizStandard.y+1) ], drawString2, vButtonFontSize, this.clr * 0.98f, (1.0f-(1.0f - arg_opac)*0.88) - 0.02f, DRAWFLAG_NORMAL, FONT_ARIAL_STD );
}
}//vOnRender_Base
}//funOnRender_Base
// convenient way to reset these globals for keeping track of a purchase in progress.
@ -783,9 +783,9 @@ UI_BuyMenu_ResetTempVariables(void)
void
CBuyMenu_WeaponButton::vOnShow_Base(void)
CBuyMenu_WeaponButton::funOnShow_Base(void)
{
CBuyMenu_BasicButton::vOnShow_Base();
CBuyMenu_BasicButton::funOnShow_Base();
// See if this weapon can be afforded.
if(canBuyWeapon(iWeaponPurchaseID, 0, 0, 1)){
clr_render = clr;
@ -793,10 +793,10 @@ CBuyMenu_WeaponButton::vOnShow_Base(void)
// same, but draw it red to show we can't afford it at a glance.
clr_render = clrRed;
}
}//vOnShow_Base
}//funOnShow_Base
void
CBuyMenu_WeaponButton::vOnClick_Base(void)
CBuyMenu_WeaponButton::funOnClick_Base(void)
{
weapondata_basic_t weaponRef;
// Just one thing. Let's reset this to be safe (new weapon opened for seeing
@ -810,7 +810,7 @@ CBuyMenu_WeaponButton::vOnClick_Base(void)
if(!(iBitsWeaponOpt & BITS_WEAPONOPT_INSTANT)){
// normal behavior.
iWeaponTempID = iWeaponPurchaseID;
CBuyMenu_BasicButton::vOnClick_Base();
CBuyMenu_BasicButton::funOnClick_Base();
}else{
// has the instant flag? that's it, apply it if we can.
if(canBuyWeapon(iWeaponPurchaseID, 0, 0, 1) ){
@ -822,7 +822,7 @@ CBuyMenu_WeaponButton::vOnClick_Base(void)
}
}
}
}//vOnClick_Base
}//funOnClick_Base
void
@ -954,7 +954,7 @@ buymenu_btn_RemoveItem_clicked(CBuyMenu_BasicButton* arg_this)
}
//INITIALIZE_BASICBUTTON(ary_btn_removeButton[i], "7 Buy Random", 48+7,clrGreen, NULL)
ary_btn_removeButton[i].create(buttonDisplayText, hotKeyCode, clrPaleBlue, &buymenu_btn_removeButton_clicked);
ary_btn_removeButton[i].create(buttonDisplayText, hotKeyCode, clrPaleBlue, buymenu_btn_removeButton_clicked);
ary_btn_removeButton[i].bActive = TRUE;
//CBuyMenu_RemoveWeaponButton removeWeaponButtonRef2 = (CBuyMenu_RemoveWeaponButton)ary_btn_removeButton[i];
@ -968,8 +968,8 @@ buymenu_btn_RemoveItem_clicked(CBuyMenu_BasicButton* arg_this)
// Take all buttons and call their "vOnShow". See what we can and can't afford
// (color red when we can't). vOnShow should handle this appropriately per button.
// Take all buttons and call their "funOnShow". See what we can and can't afford
// (color red when we can't). funOnShow should handle this appropriately per button.
void
refreshButtons(void)
{
@ -983,7 +983,7 @@ refreshButtons(void)
//CBuyMenu_BasicButton tempButton = *ary_layerFirstButton[i2];
for(i2 = 0; i2 < ary_layerFirstButton_softLength; i2++){
tempButton = *ary_layerFirstButton[i2];
tempButton.vOnShow_Base();
tempButton.funOnShow_Base();
}// for i2 in ary_layerFirstButton
}else{
@ -993,7 +993,7 @@ refreshButtons(void)
//btnToRender = &previousLayerButton.ary_btn[i2];
int btnToRender_index_global = previousLayerButton.ary_btn_index[i2];
tempButton = *ary_btnTotal[btnToRender_index_global];
tempButton.vOnShow_Base();
tempButton.funOnShow_Base();
}
}
}
@ -1326,12 +1326,12 @@ UI_BuyMenu_Init(void)
// if the 1st layer is active (drawn to that one). Says "Cancel" there, but if on any deeper layer it reads "Go Back".
//buymenu_btn_Back.create("0 Cancel", 48, NULL, buymenu_btn_Back_clicked);
INITIALIZE_BASICBUTTON(Back, "Cancel", "0", clrPaleBluePurple, &buymenu_btn_Back_clicked)
INITIALIZE_BASICBUTTON(Back, "Cancel", "0", clrPaleBluePurple, buymenu_btn_Back_clicked)
//INITIALIZE_BASICBUTTON(Buy, "2 Buy", 48+2, NULL, 0, NULL)
INITIALIZE_BASICBUTTON(Recentconfig, "Use New Config", "1", clrGreen, &buymenu_btn_UseNewConfig_clicked)
INITIALIZE_BASICBUTTON(Recentconfig, "Use New Config", "1", clrGreen, buymenu_btn_UseNewConfig_clicked)
INITIALIZE_BASICBUTTON(Buy, "Buy", "2", clrPaleBlue, NULL)
INITIALIZE_BASICBUTTON(RemoveItem, "Remove Item", "3", clrPaleBlue, &buymenu_btn_RemoveItem_clicked)
INITIALIZE_BASICBUTTON(RemoveItem, "Remove Item", "3", clrPaleBlue, buymenu_btn_RemoveItem_clicked)
INITIALIZE_BASICBUTTON(ResetConfig, "Reset Config", "4", clrPaleBlue, NULL)
INITIALIZE_BASICBUTTON(SaveConfig, "Save Config", "5", clrPaleBlue, NULL)
INITIALIZE_BASICBUTTON(LoadConfig, "Load Config", "6", clrPaleBlue, NULL)
@ -1344,27 +1344,27 @@ UI_BuyMenu_Init(void)
// !!! INITIALIZE THE WEAPON-UPGRADE BUTTONS BEFORE THE WEAPONS THEMSELVES. Or else these will be missing at that point.
INITIALIZE_BASICBUTTON(WeaponOpt_Buy, "Buy", "1", clrGreen, &buymenu_btn_Buy_Weapon_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_Silencer, sprintf("Silencer %i", WEAPONOPT_SILENCER_COST), "2", clrPaleBlue, &buymenu_btn_Silencer_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_Lasersight, sprintf("Lasersight %i", WEAPONOPT_LASERSIGHT_COST), "3", clrPaleBlue, &buymenu_btn_Lasersight_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_Flashlight, sprintf("Flashlight %i", WEAPONOPT_FLASHLIGHT_COST), "4", clrPaleBlue, &buymenu_btn_Flashlight_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_Scope, sprintf("Scope %i", WEAPONOPT_SCOPE_COST), "5", clrPaleBlue, &buymenu_btn_Scope_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_Buy, "Buy", "1", clrGreen, buymenu_btn_Buy_Weapon_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_Silencer, sprintf("Silencer %i", WEAPONOPT_SILENCER_COST), "2", clrPaleBlue, buymenu_btn_Silencer_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_Lasersight, sprintf("Lasersight %i", WEAPONOPT_LASERSIGHT_COST), "3", clrPaleBlue, buymenu_btn_Lasersight_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_Flashlight, sprintf("Flashlight %i", WEAPONOPT_FLASHLIGHT_COST), "4", clrPaleBlue, buymenu_btn_Flashlight_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_Scope, sprintf("Scope %i", WEAPONOPT_SCOPE_COST), "5", clrPaleBlue, buymenu_btn_Scope_clicked)
// Yes, Akimbo and FullLoad use the same hotkey (number 6). They never appear on the same weapon,
// since Akimbo is only meant for some guns, and FullLoad is only meant for some melee weapons.
// TODO? And if these two were to support flexible prices (show what it costs for the currently selected weapon... akimbo & fullLoad can't be fixed to
// one constant for all weapons), their display text + prices would have to be shown as they're shown to the user.
INITIALIZE_BASICBUTTON(WeaponOpt_Akimbo, "Akimbo", "6", clrPaleBlue, &buymenu_btn_Akimbo_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_FullLoad, "FullLoad", "6", clrGreen, &buymenu_btn_FullLoad_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_Akimbo, "Akimbo", "6", clrPaleBlue, buymenu_btn_Akimbo_clicked)
INITIALIZE_BASICBUTTON(WeaponOpt_FullLoad, "FullLoad", "6", clrGreen, buymenu_btn_FullLoad_clicked)
buymenu_btn_WeaponOpt_Buy.vOnShow_Custom = &buymenu_btn_Buy_onShow;
buymenu_btn_WeaponOpt_Buy.funOnShow_Custom = buymenu_btn_Buy_onShow;
buymenu_btn_WeaponOpt_Silencer.vOnShow_Custom = &buymenu_btn_Silencer_onShow;
buymenu_btn_WeaponOpt_Lasersight.vOnShow_Custom = &buymenu_btn_Lasersight_onShow;
buymenu_btn_WeaponOpt_Flashlight.vOnShow_Custom = &buymenu_btn_Flashlight_onShow;
buymenu_btn_WeaponOpt_Scope.vOnShow_Custom = &buymenu_btn_Scope_onShow;
buymenu_btn_WeaponOpt_Akimbo.vOnShow_Custom = &buymenu_btn_Akimbo_onShow;
buymenu_btn_WeaponOpt_FullLoad.vOnShow_Custom = &buymenu_btn_FullLoad_onShow;
buymenu_btn_WeaponOpt_Silencer.funOnShow_Custom = buymenu_btn_Silencer_onShow;
buymenu_btn_WeaponOpt_Lasersight.funOnShow_Custom = buymenu_btn_Lasersight_onShow;
buymenu_btn_WeaponOpt_Flashlight.funOnShow_Custom = buymenu_btn_Flashlight_onShow;
buymenu_btn_WeaponOpt_Scope.funOnShow_Custom = buymenu_btn_Scope_onShow;
buymenu_btn_WeaponOpt_Akimbo.funOnShow_Custom = buymenu_btn_Akimbo_onShow;
buymenu_btn_WeaponOpt_FullLoad.funOnShow_Custom = buymenu_btn_FullLoad_onShow;
// TODO - ONGOING. As more weapons are entered, use this new condensed way
@ -1376,51 +1376,51 @@ UI_BuyMenu_Init(void)
weapondata_basic_t tempWeapRef;
INITIALIZE_WEAPONBUTTON(GLOCK18, "1", clrPaleBlue, NULL, Handguns)
INITIALIZE_WEAPONBUTTON(SOCOMMK23, "2", clrPaleBlue, NULL, Handguns)
INITIALIZE_WEAPONBUTTON(DESERTEAGLE, "3", clrPaleBlue, NULL, Handguns)
INITIALIZE_WEAPONBUTTON(FIVESEVEN, "4", clrPaleBlue, NULL, Handguns)
INITIALIZE_WEAPONBUTTON(BERETTA, "5", clrPaleBlue, NULL, Handguns)
INITIALIZE_WEAPONBUTTON(AKIMBOCOLTS, "6", clrPaleBlue, NULL, Handguns)
INITIALIZE_WEAPONBUTTON(GLOCK20, "7", clrPaleBlue, NULL, Handguns)
INITIALIZE_WEAPONBUTTON(RUGERMK1, "8", clrPaleBlue, NULL, Handguns)
INITIALIZE_WEAPONBUTTON(RAGINGBULL, "9", clrPaleBlue, NULL, Handguns)
INITIALIZE_WEAPONBUTTON(CONTENDERG2, "A", clrPaleBlue, NULL, Handguns)
INITIALIZE_WEAPONBUTTON(GLOCK18, "1", clrPaleBlue, Handguns)
INITIALIZE_WEAPONBUTTON(SOCOMMK23, "2", clrPaleBlue, Handguns)
INITIALIZE_WEAPONBUTTON(DESERTEAGLE, "3", clrPaleBlue, Handguns)
INITIALIZE_WEAPONBUTTON(FIVESEVEN, "4", clrPaleBlue, Handguns)
INITIALIZE_WEAPONBUTTON(BERETTA, "5", clrPaleBlue, Handguns)
INITIALIZE_WEAPONBUTTON(AKIMBOCOLTS, "6", clrPaleBlue, Handguns)
INITIALIZE_WEAPONBUTTON(GLOCK20, "7", clrPaleBlue, Handguns)
INITIALIZE_WEAPONBUTTON(RUGERMK1, "8", clrPaleBlue, Handguns)
INITIALIZE_WEAPONBUTTON(RAGINGBULL, "9", clrPaleBlue, Handguns)
INITIALIZE_WEAPONBUTTON(CONTENDERG2, "A", clrPaleBlue, Handguns)
INITIALIZE_WEAPONBUTTON(MINIUZI, "1", clrPaleBlue, NULL, SMGs)
INITIALIZE_WEAPONBUTTON(MP5SD, "2", clrPaleBlue, NULL, SMGs)
INITIALIZE_WEAPONBUTTON(MP5K, "3", clrPaleBlue, NULL, SMGs)
INITIALIZE_WEAPONBUTTON(MINIUZI, "1", clrPaleBlue, SMGs)
INITIALIZE_WEAPONBUTTON(MP5SD, "2", clrPaleBlue, SMGs)
INITIALIZE_WEAPONBUTTON(MP5K, "3", clrPaleBlue, SMGs)
INITIALIZE_WEAPONBUTTON(STEYRTMP, "4", clrPaleBlue, NULL, SMGs)
INITIALIZE_WEAPONBUTTON(HKPDW, "5", clrPaleBlue, NULL, SMGs)
INITIALIZE_WEAPONBUTTON(UMP, "6", clrPaleBlue, NULL, SMGs)
INITIALIZE_WEAPONBUTTON(STEYRTMP, "4", clrPaleBlue, SMGs)
INITIALIZE_WEAPONBUTTON(HKPDW, "5", clrPaleBlue, SMGs)
INITIALIZE_WEAPONBUTTON(UMP, "6", clrPaleBlue, SMGs)
INITIALIZE_WEAPONBUTTON(SKORPION, "7", clrPaleBlue, NULL, SMGs)
INITIALIZE_WEAPONBUTTON(MAC10, "8", clrPaleBlue, NULL, SMGs)
INITIALIZE_WEAPONBUTTON(SKORPION, "7", clrPaleBlue, SMGs)
INITIALIZE_WEAPONBUTTON(MAC10, "8", clrPaleBlue, SMGs)
INITIALIZE_WEAPONBUTTON(M4A1, "1", clrPaleBlue, NULL, Rifles)
INITIALIZE_WEAPONBUTTON(AK47, "2", clrPaleBlue, NULL, Rifles)
INITIALIZE_WEAPONBUTTON(STEYRAUG, "3", clrPaleBlue, NULL, Rifles)
INITIALIZE_WEAPONBUTTON(M16A4, "4", clrPaleBlue, NULL, Rifles)
INITIALIZE_WEAPONBUTTON(BARRETTM82, "5", clrPaleBlue, NULL, Rifles)
INITIALIZE_WEAPONBUTTON(M4A1, "1", clrPaleBlue, Rifles)
INITIALIZE_WEAPONBUTTON(AK47, "2", clrPaleBlue, Rifles)
INITIALIZE_WEAPONBUTTON(STEYRAUG, "3", clrPaleBlue, Rifles)
INITIALIZE_WEAPONBUTTON(M16A4, "4", clrPaleBlue, Rifles)
INITIALIZE_WEAPONBUTTON(BARRETTM82, "5", clrPaleBlue, Rifles)
INITIALIZE_WEAPONBUTTON(BENELLIM3, "1", clrPaleBlue, NULL, Shotguns)
INITIALIZE_WEAPONBUTTON(USAS12, "2", clrPaleBlue, NULL, Shotguns)
INITIALIZE_WEAPONBUTTON(SPAS12, "3", clrPaleBlue, NULL, Shotguns)
INITIALIZE_WEAPONBUTTON(MOSSBERG500, "4", clrPaleBlue, NULL, Shotguns)
INITIALIZE_WEAPONBUTTON(SAWEDOFF, "5", clrPaleBlue, NULL, Shotguns)
INITIALIZE_WEAPONBUTTON(BENELLIM3, "1", clrPaleBlue, Shotguns)
INITIALIZE_WEAPONBUTTON(USAS12, "2", clrPaleBlue, Shotguns)
INITIALIZE_WEAPONBUTTON(SPAS12, "3", clrPaleBlue, Shotguns)
INITIALIZE_WEAPONBUTTON(MOSSBERG500, "4", clrPaleBlue, Shotguns)
INITIALIZE_WEAPONBUTTON(SAWEDOFF, "5", clrPaleBlue, Shotguns)
// LATER - make purchaseable only if the gamemode is team/scenario. (mercs vs specialists)
INITIALIZE_WEAPONBUTTON(M61GRENADE, "1", clrPaleBlue, NULL, SpecialPurpose)
INITIALIZE_WEAPONBUTTON(M61GRENADE, "1", clrPaleBlue, SpecialPurpose)
INITIALIZE_WEAPONBUTTON(COMBATKNIFE, "2", clrPaleBlue, NULL, SpecialPurpose)
INITIALIZE_WEAPONBUTTON(M60, "3", clrPaleBlue, NULL, SpecialPurpose)
INITIALIZE_WEAPONBUTTON(KATANA, "4", clrPaleBlue, NULL, SpecialPurpose)
INITIALIZE_WEAPONBUTTON(SEALKNIFE, "5", clrPaleBlue, NULL, SpecialPurpose)
INITIALIZE_WEAPONBUTTON(COMBATKNIFE, "2", clrPaleBlue, SpecialPurpose)
INITIALIZE_WEAPONBUTTON(M60, "3", clrPaleBlue, SpecialPurpose)
INITIALIZE_WEAPONBUTTON(KATANA, "4", clrPaleBlue, SpecialPurpose)
INITIALIZE_WEAPONBUTTON(SEALKNIFE, "5", clrPaleBlue, SpecialPurpose)
//TODO - set these up. items are simpler than weapons and have no default behavior.
// in fact the kevlar just puts armor on the player at spawn, stealthshoes may as well
@ -1428,8 +1428,8 @@ UI_BuyMenu_Init(void)
// Last parameter is the cost instead of the buy category, since we don't have
// any weapondata to get the cost from.
// ...we still need the category too though.
//INITIALIZE_ITEMBUTTON_ADV(KEVLAR, "1", 48+1, clrPaleBlue, NULL, PlayerAccessory, 1900);
//INITIALIZE_ITEMBUTTON_ADV(STEALTHSHOES, "2", 48+2, clrPaleBlue, NULL, PlayerAccessory, 700);
//INITIALIZE_ITEMBUTTON_ADV(KEVLAR, "1", 48+1, clrPaleBlue, PlayerAccessory, 1900);
//INITIALIZE_ITEMBUTTON_ADV(STEALTHSHOES, "2", 48+2, clrPaleBlue, PlayerAccessory, 700);
buymenu_btn_Back_updateText(); //just in case.
@ -1474,7 +1474,7 @@ UI_BuyMenu_Draw(void)
int btnToRender_index_global;
CBuyMenu_BasicButton someThing;
CBuyMenu_BasicButton previousLayerButton;
BOOL fIsSelected;
BOOL fIsSelected = FALSE;
// Checks for clicks be done separately
@ -1514,7 +1514,7 @@ UI_BuyMenu_Draw(void)
CBuyMenu_BasicButton tempButton = *ary_layerFirstButton[i2];
fIsSelected = (tempButton.iGlobalIndex == currentLayerSelectedIndex);
(*ary_layerFirstButton[i2]).vOnRender_Base(vBtnPos, i, i2, fIsSelected);
(*ary_layerFirstButton[i2]).funOnRender_Base(vBtnPos, i, i2, fIsSelected);
vBtnPos.y += (vButtonSizStandard.y + 1);
@ -1548,7 +1548,7 @@ UI_BuyMenu_Draw(void)
fIsSelected = (btnToRender_index_global == currentLayerSelectedIndex);
(*ary_btnTotal[btnToRender_index_global]).vOnRender_Base(vBtnPos, i, i2, fIsSelected);
(*ary_btnTotal[btnToRender_index_global]).funOnRender_Base(vBtnPos, i, i2, fIsSelected);
vBtnPos.y += (vButtonSizStandard.y + 1);
}// for i2 in this layer's buttons.
@ -1568,7 +1568,7 @@ UI_BuyMenu_Draw(void)
backButtonRow = ary_layerFirstButton_softLength;
}
buymenu_btn_Back.vOnRender_Base(vBtnPos, i, backButtonRow, fIsSelected);
buymenu_btn_Back.funOnRender_Base(vBtnPos, i, backButtonRow, fIsSelected);
vBtnPos.y += (vButtonSizStandard.y + 1);
}

View file

@ -38,7 +38,7 @@
///////////////////////////////////////////////////////////////////////////////
#includelist
../../../src/shared/fteextensions.qc
../../../src/gs-entbase/server/defs.h

View file

@ -2,6 +2,8 @@
#define ASSIGN_AMMODATA(arg_constName) ary_ammoData[AMMO_ID::##arg_constName] = (ammodata_t*) &ammo_##arg_constName;
#define DECLARE_AMMODATA(arg_varName, arg_sDisplayName, arg_fPricePerBullet, arg_iMax) ammodata_t ammo_##arg_varName = {arg_sDisplayName, arg_fPricePerBullet, arg_iMax};
#define ASSIGN_SHELLEJECTDATA(arg_constName) ary_shellEjectData[SHELLEJECT_ID::##arg_constName] = (shellejectdata_t*) &shelleject_##arg_constName;
#define DECLARE_SHELLEJECTDATA(arg_varName, arg_sModelPath, arg_sTouchSound) shellejectdata_t shelleject_##arg_varName = {arg_sModelPath, arg_sTouchSound};
enum AMMO_ID{
@ -38,3 +40,40 @@ typedef struct{
} ammodata_t;
// for shell ejection effects.
// Some are identical or near-identical, could have been intended to be unique
// models at some point but never happened?
enum SHELLEJECT_ID{
NONE = 0,
// Nearly identical, lighting looks to be the only difference, could even be
// randomly picked for all I know.
// Weapons will only use _56 of the two for now
_56,
_556,
// These are identical, exact same filesize.
// _GENERIC refers to shell.mdl
// _22 is most likely referring to the luger's ammo, _9MM from the similarly named
// ammo type. Still using those first in weapons involving those
_22,
_9MM,
_GENERIC,
_SHOTGUN, // red
_SHOTGUN_BLUE,
_SHOTGUN_GOLD,
LAST_ID
};
// any other info tied to shell choice?
typedef struct{
string sModelPath;
// script file (.sndshd) for hitting something, not a direct .wav file
string sTouchSound;
} shellejectdata_t;

View file

@ -13,3 +13,15 @@ DECLARE_AMMODATA(_50BMG, "50BMG", 100, 20)
DECLARE_AMMODATA(_SHELLS, "SHELLS", 16, 60)
DECLARE_AMMODATA(_32ACP, ".32 ACP", 0.5, 300)
DECLARE_AMMODATA(_7P62X51MM, "7.62 x 51mm", 30, 35)
DECLARE_SHELLEJECTDATA(NONE, "", "")
DECLARE_SHELLEJECTDATA(_56, "models/56_shell.mdl", "modelevent_shell.land")
DECLARE_SHELLEJECTDATA(_556, "models/556_shell.mdl", "modelevent_shell.land")
DECLARE_SHELLEJECTDATA(_22, "models/22_shell.mdl", "modelevent_shell.land")
DECLARE_SHELLEJECTDATA(_9MM, "models/9mm_shell.mdl", "modelevent_shell.land")
DECLARE_SHELLEJECTDATA(_GENERIC, "models/shell.mdl", "modelevent_shell.land")
DECLARE_SHELLEJECTDATA(_SHOTGUN, "models/shotgun_shell.mdl", "modelevent_shotgunshell.land")
DECLARE_SHELLEJECTDATA(_SHOTGUN_BLUE, "models/shotgun_shell_blue.mdl", "modelevent_shotgunshell.land")
DECLARE_SHELLEJECTDATA(_SHOTGUN_GOLD, "models/shotgun_shell_gold.mdl", "modelevent_shotgunshell.land")

View file

@ -75,21 +75,11 @@ enum TS_Team{
//TAGGG - Still need to remove some irrelevant ones like BUYZONE,, ESCAPEZONE, WON_T, etc.
// Also starting at stat 34? Feel some constant would be more comfortable for that, might not be an option though.
enum {
STAT_BUYZONE = STAT_BUILTIN_SEPARATOR,
STAT_MONEY = STAT_BUILTIN_SEPARATOR,
STAT_MONEY,
STAT_FLAGS,
STAT_PROGRESS,
STAT_TEAM,
//STAT_TEAM, // will we ever need that?
STAT_GAMETIME,
STAT_GAMESTATE,
/*
STAT_WON_T,
STAT_WON_CT,
*/
// NEW.
STAT_RULE_MONEYALLOWED,
STAT_RULE_MAXWEIGHTSLOTS

View file

@ -1,4 +1,18 @@
#includelist
// If enabled, pressing left and right fire within a small amount of time
// (more forgiving than the default "same-frame only" timing) lets firing
// immediately change into the akimbo dual-fire animation.
// Should not cause any more than the net number of bullets expected for
// firing both weapons. That is, left-fire, 80 milliseconds, right-fire will
// mean the left-play anim plays (fired once), then the dual-fire anim plays,
// but it should remember that the left weapon already fired, and so only fire
// the right weapon on the tolerance-allowed dual-fire anim. 2 bullet holes,
// not 3.
//#define AKIMBO_SEMI_DUAL_TOLERANCE
#includelist
//TAGGG - NEW

View file

@ -125,6 +125,9 @@ class player:base_player
// equipped. Not that it could ever change while not equipped anyway.
int prev_forceBodygroup1Submodel;
// During a shell-eject event, what member of aryShellEjectData do I use for the model
// and hitsound script file to use? Set on setting the event
int iShellEjectType;
// WEAPON KICKBACK STUFF.
// Way it works is a little different from the average (Half-Life and Counterstrike).

View file

@ -53,7 +53,7 @@ typedef struct{
int typeID;
string sDisplayName;
int iSubmodelChoice;
void(void) vOnTouch;
void(void) funOnTouch;
// SPECIFIC TO INSTANT EFFECT
// ...nothing. Think about it, it's touched and it's gone.
@ -69,17 +69,17 @@ typedef struct{
int typeID;
string sDisplayName;
int iSubmodelChoice;
void(void) vOnTouch;
void(void) funOnTouch;
// SPECIFIC TO USABLE
// How long do I last once used?
float fActiveDuration;
// What do I do when used? Generally set some stat(s)/flag(s) to get the effect,
// like telling bullets, player movement, etc. how much to be slowed down by for instance.
void(player pl) vOnUse;
void(player pl) funOnUse;
// At the end of my duration, how do I reset the things I set to act as though nothing happened?
// Should run on player death or disconnect (if necessary) too as to not leave lingering effects.
void(player pl) vOnEnd;
void(player pl) funOnEnd;
// Note that we have no think effect. Nothing could be done frame-by-frame that would help
// any of the powerups do what it needs to. Speed modifiers of any sort (slow-mo) can't force
// nearby stuff to move slower directly, it sets a flag on use that tells physics to move that stuff

View file

@ -18,6 +18,9 @@ void SharedGame_Precache(void){
precache_model("models/powerup.mdl");
// In FreeTS, looks like shell eject effects are precached both client & serverside
// (so here in shared/precache.qc is good).
// nearly identical..?
precache_model("models/56_shell.mdl");
precache_model("models/556_shell.mdl");
@ -34,7 +37,8 @@ void SharedGame_Precache(void){
// physics-related / slow-mo?
precache_model("models/bullet.mdl");
precache_model("models/long_bullet.mdl");
// some model for dirt effects?
precache_model("models/pellet.mdl");

View file

@ -772,6 +772,7 @@ typedef struct{
//TODO. Is extern'ing these earlier possible?
ammodata_t* ary_ammoData[AMMO_ID::LAST_ID];
shellejectdata_t* ary_shellEjectData[SHELLEJECT_ID::LAST_ID];
//weapondata_normal_t* ary_weaponData[WEAPON_ID::LAST_ID];
//Void pointer should be fine, right? Cast to the right weapondata_ struct above (typeID tells what that is).
@ -804,22 +805,28 @@ void weapon_base_onAttack(player pl, weapondata_basic_t* basePRef, weapondynamic
void weapon_base_onAttack_multi(player pl, weapondata_basic_t* basePRef, weapondynamic_t arg_thisWeapon, int shellCount, int attackTypeUsed);
void weapon_base_burstFire(player pl, weapondata_basic_t* basePRef, weapondynamic_t arg_thisWeapon, int attackTypeUsed, int shotCount, float shotDelay);
void weapon_gun_burstFire(player pl, weapondata_gun_t* basePRef, weapondynamic_t arg_thisWeapon, int attackTypeUsed, int shotCount, float shotDelay, float attackDelay);
BOOL weapon_shotgun_onInterrupt(player pl, weapondata_basic_t* basePRef, weapondynamic_t arg_thisWeapon);
void weapon_shotgun_reload(player pl, weapondata_basic_t* basePRef, weapondynamic_t arg_thisWeapon);
void weapon_shotgun_onThink_reloadLogic(player pl, weapondata_gun_t* basePRef, weapondynamic_t arg_thisWeapon);
void weapon_gun_akimbo_semi_primaryAttack(void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack);
void weapon_gun_akimbo_semi_secondaryAttack(void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack);
void weapon_ironsight_akimbo_semi_secondaryAttack(void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack, int arg_weaponTypeID);
BOOL weapon_akimbo_semiAttackDualHack(player pl, weapondynamic_t arg_thisWeapon, int arg_flagger, int* arg_akimboFireCallback);
BOOL weapon_akimbo_fullAttackDualHack(player pl, weapondynamic_t arg_thisWeapon, int arg_flagger, int* arg_akimboFireCallback);
BOOL weapon_akimbo_AttackDualHack(player pl, weapondynamic_t arg_thisWeapon, int arg_flagger, int* arg_akimboFireCallback);
void weapon_gun_akimbo_full_primaryAttack(void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack);
void weapon_gun_akimbo_full_secondaryAttack(void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack);
BOOL weapon_akimbo_semiAttackDualHack(player pl, weapondynamic_t arg_thisWeapon, int arg_flagger, void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack);
BOOL weapon_akimbo_fullAttackDualHack(player pl, weapondynamic_t arg_thisWeapon, int arg_flagger, void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack);
BOOL weapon_akimbo_AttackDualHack(player pl, weapondynamic_t arg_thisWeapon, int arg_flagger, void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack);
int weapon_akimbo_semiAttackChoice(player pl, weapondata_basic_t* basePRef, weapondynamic_t arg_thisWeapon, int attackTypeUsed);
int weapon_akimbo_fullAttackChoice(player pl, weapondata_basic_t* basePRef, weapondynamic_t arg_thisWeapon, int attackTypeUsed);
BOOL weapon_ironsight_ToggleIronsight(player pl, weapondata_ironsight_t* basePRef, weapondynamic_t arg_thisWeapon);
void weapon_ironsight_ToggleIronsight(player pl, weapondata_ironsight_t* basePRef, weapondynamic_t arg_thisWeapon);
void weapon_gun_Reload(player pl, weapondata_gun_t* basePRef, weapondynamic_t arg_thisWeapon );
@ -840,6 +847,8 @@ void weapon_gun_onDrawHUD(player pl, weapondata_gun_t* basePRef, weapondynamic_t
void weapon_throwable_onDrawHUD(player pl, weapondata_throwable_t* basePRef, weapondynamic_t arg_thisWeapon);
void weapon_melee_onDrawHUD(player pl, weapondata_melee_t* basePRef, weapondynamic_t arg_thisWeapon);
void weapon_ejectShell(int arg_shellEjectType);
void weapon_precache(weapondata_basic_t* basePRef);
//void weapon_gun_updateAmmo(player pl, weapondata_gun_t* basePRef, weapondynamic_t arg_thisWeapon);

View file

@ -383,20 +383,21 @@ weapon_base_onAttack_multi(player pl, weapondata_basic_t* basePRef, weapondynami
}// weapon_base_onAttack
// shotCount is how many consecutive shots to fire (no more than 3 expected),
// shotDelay is the time between them, and
// attackDelay is the time that must pass before firing is allowed again
// (as in left-click), not including the delays between shots after the 1st.
void
weapon_base_burstFire(
player pl, weapondata_basic_t* basePRef, weapondynamic_t arg_thisWeapon,
int attackTypeUsed, int shotCount, float shotDelay
weapon_gun_burstFire(
player pl, weapondata_gun_t* basePRef, weapondynamic_t arg_thisWeapon,
int attackTypeUsed, int shotCount, float shotDelay, float attackDelay
){
weapondata_basic_t baseRef = *basePRef;
float thatStuff = shotDelay * (shotCount-1) + baseRef.fAttackDelay;
weapon_base_setWholeAttackDelay(pl, thatStuff);
float totalAttackDelay = shotDelay * (shotCount-1) + attackDelay;
weapon_base_setWholeAttackDelay(pl, totalAttackDelay);
//printfline("??? %.2f ", thatStuff);
pl.aryNextBurstShotTime_softLength = shotCount;
for(int i = 0; i < shotCount; i++){
pl.aryNextBurstShotTime[i] = thatStuff - shotDelay*(i);
pl.aryNextBurstShotTime[i] = totalAttackDelay - shotDelay*(i);
//printfline("WELL #%i: %.2f", i, pl.aryNextBurstShotTime[i]);
}
@ -405,7 +406,7 @@ weapon_base_burstFire(
// and fire this very first frame.
weapon_gun_fireBurstBullet(pl, basePRef, arg_thisWeapon);
}//weapon_base_burstFire
}//weapon_gun_burstFire
@ -620,10 +621,172 @@ weapon_shotgun_onThink_reloadLogic(player pl, weapondata_gun_t* basePRef, weapon
// Handles the primaryAttack method for akimbo weapons, mostly checking whether to
// use the semiAttackDualHack or skip straight to funAttack.
// arg_funAttack is what handles firing for the akimbo weapon, something like
// "weapon_socommk23_akimbo_attack".
// No need for a separate version for ironsight for primary, nothing different
// happens there.
void
weapon_gun_akimbo_semi_primaryAttack(
void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack
){
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
#ifndef AKIMBO_SEMI_DUAL_TOLERANCE
if(input_buttons & INPUT_BUTTON3){
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
}else{
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
}
#else
// in addition to the primary input, which lead to '_primary' being called at all.
if(input_buttons & INPUT_BUTTON3){
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH, arg_funAttack)){
// nothing unusual here.
pl.akimboTest = 0;
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
}else{
}
}else{
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT, arg_funAttack)){
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
pl.akimboFirePrev = BITS_AKIMBOCHOICE_LEFT;
}
}
#endif
}
// Same as above but for akimbo semi secondary, has a separate ironsight version that
// needs to be used by ironsights.
// That version also needs the weapon type ID given for the ironsight-toggle call
void
weapon_gun_akimbo_semi_secondaryAttack(
void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack
){
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
#ifndef AKIMBO_SEMI_DUAL_TOLERANCE
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_SEMI_AUTO){
// no ironsights, nothing to do here.
}else{
// fires the right weapon always
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
}
#else
// NOTE - holding primary is impossible, would've called _primary above if so.
// Only secondary could possibly be held (and, is).
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_SEMI_AUTO){
// no ironsights, nothing to do here.
}else{
// fires the right weapon always
//weapon_socommk23_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
//return;
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, arg_funAttack)){
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
pl.akimboFirePrev = BITS_AKIMBOCHOICE_RIGHT;
}
}
#endif
}
void
weapon_ironsight_akimbo_semi_secondaryAttack(
void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack,
int arg_weaponTypeID
){
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
#ifndef AKIMBO_SEMI_DUAL_TOLERANCE
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_SEMI_AUTO){
// since secondary fire does nothing in semi-auto, we let it do ironsight stuff here
weapon_ironsight_ToggleIronsight(pl, (weapondata_ironsight_t*)ary_weaponData[arg_weaponTypeID], arg_thisWeapon);
}else{
// fires the right weapon always
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
}
#else
// NOTE - holding primary is impossible, would've called _primary above if so.
// Only secondary could possibly be held (and, is).
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_SEMI_AUTO){
// since secondary fire does nothing in semi-auto, we let it do ironsight stuff here
weapon_ironsight_ToggleIronsight(pl, (weapondata_ironsight_t*)ary_weaponData[arg_weaponTypeID], arg_thisWeapon);
}else{
// fires the right weapon always
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, arg_funAttack)){
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
pl.akimboFirePrev = BITS_AKIMBOCHOICE_RIGHT;
}
}
#endif
}
// And now for full semi weapons (holding down the mouse fires continuously)
// They don't use the DUAL_TOLERANCE system regardless of the constant.
// Also, no ironsight version, that combo never happens.
void
weapon_gun_akimbo_full_primaryAttack(
void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack
){
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
pl.akimboTest = 0;
if(input_buttons & INPUT_BUTTON3){
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
}else{
// Only intent given inputs, firing both will still happen in
// the "Full-auto" firemode
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
}
}
void
weapon_gun_akimbo_full_secondaryAttack(
void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack
){
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
pl.akimboTest = 0;
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_FREE_FULL){
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
//pl.akimboFirePrev = BITS_AKIMBOCHOICE_RIGHT;
}
}
BOOL
weapon_akimbo_AttackDualHack(
player pl, weapondynamic_t arg_thisWeapon, int arg_flagger,
int* arg_akimboFireCallback
void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack
){
//printfline("WELL WHAT. %.2f, %i, %i", pl.akimboDualFireToleranceTime, pl.akimboFirePrev, arg_flagger);
if(arg_flagger == 0){
@ -669,8 +832,10 @@ weapon_akimbo_AttackDualHack(
// Could make a table to know what to use per akimbo weapon ID, having a table
// with one space for every single weapon in the game seems pretty wasteful.
// Calls like weapon_socommk23_akimbo_attack, etc.
BOOL(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed)* tempRef = arg_akimboFireCallback;
(*tempRef)(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
//BOOL(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed)* tempRef = arg_akimboFireCallback;
//(*tempRef)(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
arg_funAttack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
//printfline("I WENT, akprev:%i aktest:%i - flagg:%i", pl.akimboFirePrev, pl.akimboTest, arg_flagger);
@ -694,12 +859,12 @@ weapon_akimbo_AttackDualHack(
BOOL
weapon_akimbo_semiAttackDualHack(
player pl, weapondynamic_t arg_thisWeapon, int arg_flagger,
int* arg_akimboFireCallback
void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack
){
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_SEMI_AUTO){
return FALSE;
}
return weapon_akimbo_AttackDualHack(pl, arg_thisWeapon, arg_flagger, arg_akimboFireCallback);
return weapon_akimbo_AttackDualHack(pl, arg_thisWeapon, arg_flagger, arg_funAttack);
}
// WARNING! Don't do this, full-firing akimbos really don't need this,
@ -708,12 +873,12 @@ weapon_akimbo_semiAttackDualHack(
BOOL
weapon_akimbo_fullAttackDualHack(
player pl, weapondynamic_t arg_thisWeapon, int arg_flagger,
int* arg_akimboFireCallback
void(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed) arg_funAttack
){
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_FULL_AUTO){
return FALSE;
}
return weapon_akimbo_AttackDualHack(pl, arg_thisWeapon, arg_flagger, arg_akimboFireCallback);
return weapon_akimbo_AttackDualHack(pl, arg_thisWeapon, arg_flagger, arg_funAttack);
}
@ -1117,7 +1282,7 @@ weapon_akimbo_fullAttackChoice(
}//weapon_akimbo_fullAttackChoice
BOOL
void
weapon_ironsight_ToggleIronsight(
player pl, weapondata_ironsight_t* basePRef,
weapondynamic_t arg_thisWeapon
@ -1125,7 +1290,6 @@ weapon_ironsight_ToggleIronsight(
//weapondata_ironsight_t* basePRef = (weapondata_ironsight_t*)ary_weaponData[WEAPON_ID::SOCOMMK23];
weapondata_ironsight_t baseRef = *basePRef;
// SEARCH ME!!!
//arg_thisWeapon.iIronSight = 0;
if(pl.isReloading == FALSE && pl.isChangingIronsight == FALSE){
@ -1154,13 +1318,12 @@ weapon_ironsight_ToggleIronsight(
//arg_thisWeapon.iIronSight = pl.recentAttackHadAmmo;
//arg_thisWeapon.iIronSight = !arg_thisWeapon.iIronSight;
return TRUE;
return;
}else{
printfline("time: %.2f weapon_ironsight_ToggleIronsight FAILED (%d, %d). current:%i", time, pl.isReloading, pl.isChangingIronsight, arg_thisWeapon.iIronSight);
}
return FALSE;
}// weapon_ironsight_ToggleIronsight
@ -1658,27 +1821,24 @@ weapon_melee_onDrawHUD(player pl, weapondata_melee_t* basePRef, weapondynamic_t
// SHELL SOUNDS:
// ts/sound/weapons/shell.wav
// ts/sound/weapons/sshell.wav
// ts/sound/weapons/sshell1.wav
// ts/sound/weapons/sshell2.wav
// ts/sound/weapons/sshell3.wav
// valve/sound/player/pl_shell1.wav
// valve/sound/player/pl_shell2.wav
// valve/sound/player/pl_shell3.wav
// ----
// * sshell1, 2, and 3 are also found in the valve folder, these appear to be clones.
// * pl_shell ones are not cloned but can still be used
// * unknown if weapons/shell and sshell are used in original TS, may only be the
// 1,2,3 ones (shell#, sshell#) for most weapons and shotguns accordingly.
//
// Not to be confused with the clientside-only event "weapon_ejectShell_event".
// This is called by weapons to add the event, handles setting the shell-type global
// for it to see. If shell-ejects are done serverside, that would not be an amazing
// idea. Per-player would be better.
void weapon_ejectShell(int arg_shellEjectType){
//ary_shellEjectData[arg_shellEjectType]...
#ifdef CLIENT
player pl = (player)self;
pl.iShellEjectType = arg_shellEjectType;
View_AddEvent(w_ejectshell_pistol, 0.0f);
#else
// anything for the playermodel? Also only do that for all players except the
// localplayer if using a viewmodel.
// ...and already this is sounding more like a job for predraw, which does handle
// players rendering players other than themselves. And yes, still clientside.
#endif
}
// Precache models and the HUD icon given in FreeTS weapondata.
// Weapon sounds and anything else not in the struct shuold be precached
@ -1871,22 +2031,6 @@ setupWeaponData(void){
/////////////////////////////////////////////////////////
ASSIGN_AMMODATA(NONE)
ASSIGN_AMMODATA(_9X19MM)
ASSIGN_AMMODATA(_45ACP)
ASSIGN_AMMODATA(_P50AE)
ASSIGN_AMMODATA(_5P7X28)
ASSIGN_AMMODATA(_10MMAUTO)
ASSIGN_AMMODATA(_P22LR)
ASSIGN_AMMODATA(_P454CASULL)
ASSIGN_AMMODATA(_5P56NATO)
ASSIGN_AMMODATA(_7P62X39MM)
ASSIGN_AMMODATA(_50BMG)
ASSIGN_AMMODATA(_SHELLS)
ASSIGN_AMMODATA(_32ACP)
ASSIGN_AMMODATA(_7P62X51MM)
ASSIGN_WEAPONDATA(NONE, none)
@ -1955,10 +2099,39 @@ setupWeaponData(void){
ary_shotgunExtra[SHOTGUN_EXTRA_ID::BENELLIM3] = &weapon_benellim3_shotgunExtra;
ary_shotgunExtra[SHOTGUN_EXTRA_ID::MOSSBERG500] = &weapon_mossberg500_shotgunExtra;
ary_shotgunExtra[SHOTGUN_EXTRA_ID::MOSSBERG500_IRONSIGHT] = &weapon_mossberg500_shotgunExtra_ironsight;
ary_shotgunExtra[SHOTGUN_EXTRA_ID::SPAS12] = &weapon_spas12_shotgunExtra;
ASSIGN_AMMODATA(NONE)
ASSIGN_AMMODATA(_9X19MM)
ASSIGN_AMMODATA(_45ACP)
ASSIGN_AMMODATA(_P50AE)
ASSIGN_AMMODATA(_5P7X28)
ASSIGN_AMMODATA(_10MMAUTO)
ASSIGN_AMMODATA(_P22LR)
ASSIGN_AMMODATA(_P454CASULL)
ASSIGN_AMMODATA(_5P56NATO)
ASSIGN_AMMODATA(_7P62X39MM)
ASSIGN_AMMODATA(_50BMG)
ASSIGN_AMMODATA(_SHELLS)
ASSIGN_AMMODATA(_32ACP)
ASSIGN_AMMODATA(_7P62X51MM)
ASSIGN_SHELLEJECTDATA(NONE)
ASSIGN_SHELLEJECTDATA(_56)
ASSIGN_SHELLEJECTDATA(_556)
ASSIGN_SHELLEJECTDATA(_22)
ASSIGN_SHELLEJECTDATA(_9MM)
ASSIGN_SHELLEJECTDATA(_GENERIC)
ASSIGN_SHELLEJECTDATA(_SHOTGUN)
ASSIGN_SHELLEJECTDATA(_SHOTGUN_BLUE)
ASSIGN_SHELLEJECTDATA(_SHOTGUN_GOLD)
}//setupWeaponData
@ -2042,10 +2215,8 @@ getAmmoTypeOfWeapon(int arg_weaponID)
// check for being redundant with the events_custom.qc (whatever) ejectshell - like
// method!
// Could likely combine this better with that alternate way, but both should
// effectively do the exact same thing.
// This is based off what the HL glock does, adjust with custom shell-choices per
// different weapons that use them.
// Is HL's "w_shotgun_ejectshell" even any different from this besides shell-model
@ -2056,20 +2227,33 @@ getAmmoTypeOfWeapon(int arg_weaponID)
// Try testing FreeHL or FreeCS, do you see your own shells in thirdperson on firing
// and (multiplayer) do other players see your shells on firing?
// (based off w_glock_ejectshell)
// TODO: rename to weapon_ejectShell_event
#ifdef CLIENT
void
w_ejectshell_pistol(void)
{
static void w_glock_ejectshell_death(void) {
player pl = (player)pSeat->m_ePlayer;
static void weapon_ejectshell_remove(void) {
remove(self);
}
static void w_glock_ejectshell_touch(void) {
if (other == world)
static void weapon_ejectshell_touch(void) {
if(other == world){
// TODO, use custom
Sound_Play(self, CHAN_BODY, "modelevent_shell.land");
//shellejectdata_t* mySED = aryShellEjectData[pl.iShellEjectType];
//Sound_Play(self, CHAN_BODY, (*mySED).sTouchSound);
}
}
vector vOrigin;
entity eShell = spawn();
// TODO, use custom
setmodel(eShell, "models/shell.mdl");
//shellejectdata_t* mySED2 = aryShellEjectData[pl.iShellEjectType];
//setmodel(eShell, (*mySED2).sModelPath);
eShell.solid = SOLID_BBOX;
eShell.movetype = MOVETYPE_BOUNCE;
eShell.drawmask = MASK_ENGINE;
@ -2080,14 +2264,50 @@ w_ejectshell_pistol(void)
eShell.velocity += (v_forward * 0);
eShell.velocity += (v_right * 80);
eShell.velocity += (v_up * 100);
eShell.touch = w_glock_ejectshell_touch;
eShell.touch = weapon_ejectshell_touch;
eShell.avelocity = [0,45,900];
eShell.think = w_glock_ejectshell_death;
eShell.think = weapon_ejectshell_remove;
eShell.nextthink = time + 2.5f;
setsize(eShell, [0,0,0], [0,0,0]);
setorigin(eShell, pSeat->m_eViewModel.origin + (v_forward * 26) + (v_right * 8) + (v_up * -4));
}
// TODO: I think attachments supply a direction too, fuzzy on the details,
// player predraw (client/player.qc) definitely has something like that to put the
// viewmodel laser-start or flashlight sprite glow effect in the right place.
// FreeHL way (forget all the rest if so)
vOrigin = pSeat->m_eViewModel.origin + (v_forward * 26) + (v_right * 8) + (v_up * -4);
/*
// way #1
//vOrigin = pSeat->m_eViewModel.origin;
// way #2: old codebase way?
//vOrigin = pSeat->m_vecPredictedOrigin + [0, 0, getstatf(STAT_VIEWHEIGHT)];
// way #3
// "pSeat->m_iVMBones + 1" gets the first attachment, add more to get other
// attachments, or places on the model that can be helpful to tie into
// Although this is still making shell ejections happen at the end of the muzzle
// and the other attachments just go further out?
vector vOffset = gettaginfo(pSeat->m_eViewModel, pSeat->m_iVMBones + 1);
printfline("WHAT?! %.2f %.2f %.2f", vOffset[0], vOffset[1], vOffset[2]);
// way #3a
// assumes a vOrigin provided by earlier
//vOrigin += (v_forward * vOffset[0]);
//vOrigin += (v_right * -vOffset[1]);
//vOrigin += (v_up * vOffset[2]) ;
// way #3b
// or only be vOffset
vOrigin = vOffset;
*/
setorigin(eShell, vOrigin);
}//weapon_ejectShell_event
// also clientside only, dealing with configs

View file

@ -131,7 +131,7 @@ w_akimbocolts_holster(void)
// Akimbo weapons consistently.
// Putting it here avoids duplicating a bunch of code.
// Also, "attackTypeUsed" is whether primary (FALSE) or secondary (TRUE) lead to this point.
BOOLEAN weapon_akimbocolts_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
void weapon_akimbocolts_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
float randomChoice;
//weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
@ -148,16 +148,11 @@ BOOLEAN weapon_akimbocolts_akimbo_attack(player pl, weapondynamic_t arg_thisWeap
// because I am not copy/pasting this monstrosity 5 times.
finalAkimboChoice = weapon_akimbo_semiAttackChoice(pl, ary_weaponData[WEAPON_ID::AKIMBOCOLTS], arg_thisWeapon, attackTypeUsed);
#ifdef CLIENT
SAVE_STATE(pl.nextAkimboAttackPreference);
#endif
if(finalAkimboChoice == -1){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
if(pl.recentAttackHadAmmo == FALSE){
if((finalAkimboChoice & BITS_AKIMBOCHOICE_LEFT)){
PLAY_CLICK_SOUND_LEFT
@ -165,14 +160,14 @@ BOOLEAN weapon_akimbocolts_akimbo_attack(player pl, weapondynamic_t arg_thisWeap
if((finalAkimboChoice & BITS_AKIMBOCHOICE_RIGHT)){
PLAY_CLICK_SOUND_RIGHT
}
return FALSE;
return;
}
// ?? Is this even possible?
if(finalAkimboChoice == 0){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
// Use me for things the recent firing round already did to avoid redundancy.
@ -185,16 +180,12 @@ BOOLEAN weapon_akimbocolts_akimbo_attack(player pl, weapondynamic_t arg_thisWeap
weapon_base_onAttack(pl, ary_weaponData[WEAPON_ID::AKIMBOCOLTS], arg_thisWeapon, effectiveAkimboChoice);
#if 0
if(effectiveAkimboChoice & BITS_AKIMBOCHOICE_LEFT){
TS_Weapons_PlaySoundDirect(pl, "weapons/gold/gold-fire.wav");
SoundPitched_Send(pl, SNDP_AKIMBOCOLTS_FIRE);
}
if(effectiveAkimboChoice & BITS_AKIMBOCHOICE_RIGHT){
TS_Weapons_PlaySoundDirect(pl, "weapons/gold/gold-fire.wav");
SoundPitched_Send(pl, SNDP_AKIMBOCOLTS_FIRE);
}
#else
SoundPitched_Send(pl, SNDP_AKIMBOCOLTS_FIRE);
#endif
if(pl.akimboTest == 0 && !(finalAkimboChoice == BITS_AKIMBOCHOICE_BOTH)){
@ -262,62 +253,20 @@ BOOLEAN weapon_akimbocolts_akimbo_attack(player pl, weapondynamic_t arg_thisWeap
weapon_base_setWholeAttackDelay(pl, (*ary_weaponData[pl.activeweapon]).fAttackDelay * 1);
}
return TRUE;
}//END OF weapon_akimbocolts_akimbo_attack
}// weapon_akimbocolts_akimbo_attack
void
w_akimbocolts_primary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
// in addition to the primary input, which lead to '_primary' being called at all.
if(input_buttons & INPUT_BUTTON3){
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH, &weapon_akimbocolts_akimbo_attack)){
// nothing unusual here.
pl.akimboTest = 0;
weapon_akimbocolts_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
}else{
}
}else{
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT, &weapon_akimbocolts_akimbo_attack)){
weapon_akimbocolts_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
pl.akimboFirePrev = BITS_AKIMBOCHOICE_LEFT;
}
}
weapon_gun_akimbo_semi_primaryAttack(weapon_akimbocolts_akimbo_attack);
}
void
w_akimbocolts_secondary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
// NOTE - holding primary is impossible, would've called _primary above if so.
// Only secondary could possibly be held (and, is).
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_SEMI_AUTO){
// no ironsights, nothing to do here.
}else{
// fires the right weapon always
//weapon_akimbocolts_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
//return;
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, &weapon_akimbocolts_akimbo_attack)){
weapon_akimbocolts_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
pl.akimboFirePrev = BITS_AKIMBOCHOICE_RIGHT;
}
}
weapon_gun_akimbo_semi_secondaryAttack(weapon_akimbocolts_akimbo_attack);
}

View file

@ -141,7 +141,8 @@ w_barrettm82_primary(void)
}
SoundPitched_Send(pl, SNDP_BARRETTM82_FIRE);
randomChoice = random();
if(randomChoice < 0.5){
TS_Weapons_ViewAnimation(weaponseq_barrettm82::shoot, 31.0f/30.0f);
}else{

View file

@ -153,7 +153,7 @@ w_beretta_akimbo_holster(void)
// Akimbo weapons consistently.
// Putting it here avoids duplicating a bunch of code.
// Also, "attackTypeUsed" is whether primary (FALSE) or secondary (TRUE) lead to this point.
BOOLEAN weapon_beretta_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
void weapon_beretta_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
float randomChoice;
//weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
@ -170,16 +170,11 @@ BOOLEAN weapon_beretta_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon,
// because I am not copy/pasting this monstrosity 5 times.
finalAkimboChoice = weapon_akimbo_semiAttackChoice(pl, ary_weaponData[WEAPON_ID::BERETTA_AKIMBO], arg_thisWeapon, attackTypeUsed);
#ifdef CLIENT
SAVE_STATE(pl.nextAkimboAttackPreference);
#endif
if(finalAkimboChoice == -1){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
if(pl.recentAttackHadAmmo == FALSE){
if((finalAkimboChoice & BITS_AKIMBOCHOICE_LEFT)){
PLAY_CLICK_SOUND_LEFT
@ -187,14 +182,14 @@ BOOLEAN weapon_beretta_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon,
if((finalAkimboChoice & BITS_AKIMBOCHOICE_RIGHT)){
PLAY_CLICK_SOUND_RIGHT
}
return FALSE;
return;
}
// ?? Is this even possible?
if(finalAkimboChoice == 0){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
// Use me for things the recent firing round already did to avoid redundancy.
@ -313,63 +308,20 @@ BOOLEAN weapon_beretta_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon,
weapon_base_setWholeAttackDelay(pl, (*ary_weaponData[pl.activeweapon]).fAttackDelay * 1);
}
return TRUE;
}//END OF weapon_beretta_akimbo_attack
}// weapon_beretta_akimbo_attack
void
w_beretta_akimbo_primary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
// in addition to the primary input, which lead to '_primary' being called at all.
if(input_buttons & INPUT_BUTTON3){
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH, &weapon_beretta_akimbo_attack)){
// nothing unusual here.
pl.akimboTest = 0;
weapon_beretta_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
}else{
}
}else{
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT, &weapon_beretta_akimbo_attack)){
weapon_beretta_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
pl.akimboFirePrev = BITS_AKIMBOCHOICE_LEFT;
}
}
weapon_gun_akimbo_semi_primaryAttack(weapon_beretta_akimbo_attack);
}
void
w_beretta_akimbo_secondary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
// NOTE - holding primary is impossible, would've called _primary above if so.
// Only secondary could possibly be held (and, is).
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_SEMI_AUTO){
// no ironsights, nothing to do here.
}else{
// fires the right weapon always
//weapon_beretta_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
//return;
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, &weapon_beretta_akimbo_attack)){
weapon_beretta_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
pl.akimboFirePrev = BITS_AKIMBOCHOICE_RIGHT;
}
}
weapon_gun_akimbo_semi_secondaryAttack(weapon_beretta_akimbo_attack);
}
void

View file

@ -119,8 +119,6 @@ w_fiveseven_akimbo_holster(void)
var int leftCount = 0;
var int rightCount = 0;
// General attack method to be called by primary or secondary fire as needed.
// The firemode used determines whether only pressing primary fire works (alternate b/w
@ -128,7 +126,7 @@ var int rightCount = 0;
// Akimbo weapons consistently.
// Putting it here avoids duplicating a bunch of code.
// Also, "attackTypeUsed" is whether primary (FALSE) or secondary (TRUE) lead to this point.
BOOLEAN weapon_fiveseven_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
void weapon_fiveseven_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
//weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
//special case
@ -144,16 +142,11 @@ BOOLEAN weapon_fiveseven_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon
// because I am not copy/pasting this monstrosity 5 times.
finalAkimboChoice = weapon_akimbo_semiAttackChoice(pl, ary_weaponData[WEAPON_ID::FIVESEVEN_AKIMBO], arg_thisWeapon, attackTypeUsed);
#ifdef CLIENT
SAVE_STATE(pl.nextAkimboAttackPreference);
#endif
if(finalAkimboChoice == -1){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
/*
// DEBUG
if(finalAkimboChoice > 0){
@ -167,26 +160,17 @@ BOOLEAN weapon_fiveseven_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon
if((finalAkimboChoice & BITS_AKIMBOCHOICE_RIGHT)){
PLAY_CLICK_SOUND_RIGHT
}
return FALSE;
return;
}
// ?? Is this even possible?
if(finalAkimboChoice == 0){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
// DEBUG!!!
if((finalAkimboChoice & BITS_AKIMBOCHOICE_LEFT)){
leftCount++;
}
if((finalAkimboChoice & BITS_AKIMBOCHOICE_RIGHT)){
rightCount++;
}
printfline("COUNTS! %i %i", leftCount, rightCount);
// Use me for things the recent firing round already did to avoid redundancy.
// That is, if left-click was pressed a fraction of a second ago and then right-click
// to force leading here to play the dual-fire anim, no need to do the muzzle flash,
@ -268,63 +252,20 @@ BOOLEAN weapon_fiveseven_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon
weapon_base_setWholeAttackDelay(pl, (*ary_weaponData[pl.activeweapon]).fAttackDelay * 1);
}
return TRUE;
}//END OF weapon_fiveseven_akimbo_attack
}// weapon_fiveseven_akimbo_attack
void
w_fiveseven_akimbo_primary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
// in addition to the primary input, which lead to '_primary' being called at all.
if(input_buttons & INPUT_BUTTON3){
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH, &weapon_fiveseven_akimbo_attack)){
// nothing unusual here.
pl.akimboTest = 0;
weapon_fiveseven_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
}else{
}
}else{
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT, &weapon_fiveseven_akimbo_attack)){
weapon_fiveseven_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
pl.akimboFirePrev = BITS_AKIMBOCHOICE_LEFT;
}
}
weapon_gun_akimbo_semi_primaryAttack(weapon_fiveseven_akimbo_attack);
}
void
w_fiveseven_akimbo_secondary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
// NOTE - holding primary is impossible, would've called _primary above if so.
// Only secondary could possibly be held (and, is).
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_SEMI_AUTO){
// no ironsight.
}else{
// fires the right weapon always
//weapon_fiveseven_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
//return;
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, &weapon_fiveseven_akimbo_attack)){
weapon_fiveseven_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
pl.akimboFirePrev = BITS_AKIMBOCHOICE_RIGHT;
}
}
weapon_gun_akimbo_semi_secondaryAttack(weapon_fiveseven_akimbo_attack);
}
void

View file

@ -176,12 +176,14 @@ w_glock18_primary(void)
#ifdef CLIENT
View_ShowMuzzleflash(MUZZLE_SMALL);
// Why even be an event? Sometimes it happens, sometimes it doesn't?
// shell ejection can happen instantly in the weapon_base_onAttack call
// further down anyway
View_AddEvent(w_ejectshell_pistol, 0.0f);
#endif
// TODO: replace View_AddEvent
weapon_ejectShell(SHELLEJECT_ID::_9MM);
weapon_base_onAttack(pl, ary_weaponData[WEAPON_ID::GLOCK18], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
// nothing too special for that.

View file

@ -182,7 +182,7 @@ w_karate_primary(void)
// moved to a method so that early termination does not stop too much.
void w_karate_determineSecondaryAttack(MELEE_HIT_RESPONSE* hitRep, int* meleeAnimToPlay){
void w_karate_determineSecondaryAttack(MELEE_HIT_RESPONSE& hitRep, int& meleeAnimToPlay){
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
float curSpeed;
@ -192,8 +192,8 @@ void w_karate_determineSecondaryAttack(MELEE_HIT_RESPONSE* hitRep, int* meleeAni
if(input_buttons & INPUT_BUTTON8){
//crouching?
//spin kick
(*meleeAnimToPlay) = 1;
(*hitRep) = weapon_base_onPrimaryAttack_melee(pl, ary_weaponData[WEAPON_ID::KARATE], arg_thisWeapon, 40 * pl.fKarateStamina, 72);
meleeAnimToPlay = 1;
hitRep = weapon_base_onPrimaryAttack_melee(pl, ary_weaponData[WEAPON_ID::KARATE], arg_thisWeapon, 40 * pl.fKarateStamina, 72);
weapon_base_setWholeAttackDelay(pl, 1);
pl.fMoveBlockDelay = time + 1;
pl.fKarateStamina = bound(0, pl.fKarateStamina - 0.25, 1);
@ -213,8 +213,8 @@ void w_karate_determineSecondaryAttack(MELEE_HIT_RESPONSE* hitRep, int* meleeAni
if(dotproduct(_2d_dir, velocity_dir) <= -0.7 && GET_VIEW_ANGLES.x >= -55 && GET_VIEW_ANGLES.x <= 55){
// moving back-kick
(*meleeAnimToPlay) = 2;
(*hitRep) = weapon_base_onPrimaryAttack_melee_fromCustomDirection(pl, ary_weaponData[WEAPON_ID::KARATE], arg_thisWeapon, 30 * pl.fKarateStamina, 76, -v_forward);
meleeAnimToPlay = 2;
hitRep = weapon_base_onPrimaryAttack_melee_fromCustomDirection(pl, ary_weaponData[WEAPON_ID::KARATE], arg_thisWeapon, 30 * pl.fKarateStamina, 76, -v_forward);
weapon_base_setWholeAttackDelay(pl, 1);
pl.fMoveBlockDelay = time + 1;
//TAGGG - NOTE. Why is this stamina-loss in original TS so high?
@ -224,8 +224,8 @@ void w_karate_determineSecondaryAttack(MELEE_HIT_RESPONSE* hitRep, int* meleeAni
pl.fKarateStamina = bound(0, pl.fKarateStamina - 0.40, 1);
}else{
//moving-kick
(*meleeAnimToPlay) = 0;
(*hitRep) = weapon_base_onPrimaryAttack_melee_fromCustomDirection(pl, ary_weaponData[WEAPON_ID::KARATE], arg_thisWeapon, 30 * pl.fKarateStamina, 74, v_forward);
meleeAnimToPlay = 0;
hitRep = weapon_base_onPrimaryAttack_melee_fromCustomDirection(pl, ary_weaponData[WEAPON_ID::KARATE], arg_thisWeapon, 30 * pl.fKarateStamina, 74, v_forward);
weapon_base_setWholeAttackDelay(pl, 0.53);
pl.fMoveBlockDelay = time + 0.46;
pl.fKarateStamina = bound(0, pl.fKarateStamina - 0.16, 1);
@ -237,8 +237,8 @@ void w_karate_determineSecondaryAttack(MELEE_HIT_RESPONSE* hitRep, int* meleeAni
if(input_movevalues.x < -40 && GET_VIEW_ANGLES.x >= -55 && GET_VIEW_ANGLES.x <= 55){
//standing back-kick.
makevectors(GET_VIEW_ANGLES);
(*meleeAnimToPlay) = 2;
(*hitRep) = weapon_base_onPrimaryAttack_melee_fromCustomDirection(pl, ary_weaponData[WEAPON_ID::KARATE], arg_thisWeapon, 30 * pl.fKarateStamina, 74, -v_forward);
meleeAnimToPlay = 2;
hitRep = weapon_base_onPrimaryAttack_melee_fromCustomDirection(pl, ary_weaponData[WEAPON_ID::KARATE], arg_thisWeapon, 30 * pl.fKarateStamina, 74, -v_forward);
weapon_base_setWholeAttackDelay(pl, 1);
pl.fMoveBlockDelay = time + 1;
pl.fKarateStamina = bound(0, pl.fKarateStamina - 0.3, 1);
@ -247,8 +247,8 @@ void w_karate_determineSecondaryAttack(MELEE_HIT_RESPONSE* hitRep, int* meleeAni
// DEFAULT: nothing special then.
(*meleeAnimToPlay) = 0;
(*hitRep) = weapon_base_onPrimaryAttack_melee(pl, ary_weaponData[WEAPON_ID::KARATE], arg_thisWeapon, 30 * pl.fKarateStamina, 66);
meleeAnimToPlay = 0;
hitRep = weapon_base_onPrimaryAttack_melee(pl, ary_weaponData[WEAPON_ID::KARATE], arg_thisWeapon, 30 * pl.fKarateStamina, 66);
weapon_base_setWholeAttackDelay(pl, 0.53);
pl.fMoveBlockDelay = time + 0.46;
@ -266,7 +266,10 @@ w_karate_secondary(void)
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
float randomChoice;
MELEE_HIT_RESPONSE hitRep;
// a warning if this isn't defaulted, really?
// The whole point of being sent as a reference in determineSecondaryAttack is
// to give it a value though, I think this FTE warning is wrong, but satisfying anyway
MELEE_HIT_RESPONSE hitRep = MELEE_HIT_RESPONSE::NONE;
int meleeAnimToPlay = 0;
if(pl.w_attack_next > 0){
@ -279,7 +282,7 @@ w_karate_secondary(void)
// TODO - base karate melee damage? I forget.
w_karate_determineSecondaryAttack(&hitRep, &meleeAnimToPlay);
w_karate_determineSecondaryAttack(hitRep, meleeAnimToPlay);
//pl.fUncrouchBlockDelay = time + 1.0f;
//Animation_ShootWeapon( self );

View file

@ -150,12 +150,21 @@ w_m16a4_primary(void)
INPUT_PRIMARY_TAP_GATE
}
if(
pl.aryNextBurstShotTime_listenIndex != -1 &&
arg_thisWeapon.iFireMode != BITS_FIREMODE_NONE
){
// the player is trying to manually fire while burst-fire is in the middle
// of sending shots? STOP
return;
}
if (!arg_thisWeapon.iClipLeft || WEAPON_UNDERWATER_CHECK) {
PLAY_CLICK_SOUND
return;
}
SoundPitched_Send(pl, SNDP_M16A4_FIRE);
SoundPitched_Send(pl, SNDP_M16A4_FIRE);
if(!arg_thisWeapon.iIronSight){
randomChoice = random();
@ -190,17 +199,7 @@ w_m16a4_primary(void)
if(arg_thisWeapon.iFireMode == BITS_FIREMODE_BURST)
{
/*
#ifdef SERVER
weapon_base_burstFire(pl, ary_weaponData[WEAPON_ID::M16A4], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, 3, 0.11);
// signal for server logic... for now.
return FALSE;
#else
weapon_base_onAttack(pl, ary_weaponData[WEAPON_ID::M16A4], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
#endif
*/
weapon_base_burstFire(pl, ary_weaponData[WEAPON_ID::M16A4], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, 3, 0.02);
weapon_gun_burstFire(pl, (weapondata_gun_t*)ary_weaponData[WEAPON_ID::M16A4], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, 3, 0.02, 0.18);
}
else if(arg_thisWeapon.iFireMode == BITS_FIREMODE_SEMI)
{

View file

@ -7,8 +7,8 @@ enum weaponseq_m61grenade{
throw_slide
};
BOOL weapon_grenade_onInputPress(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed);
//BOOL weapon_grenade_onInputRelease(player pl, weapondynamic_t arg_thisWeapon);
void weapon_grenade_onInputPress(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed);
//void weapon_grenade_onInputRelease(player pl, weapondynamic_t arg_thisWeapon);
void weapon_m61grenade_onPrimaryAttackRelease(player pl, weapondynamic_t arg_thisWeapon){
@ -269,7 +269,7 @@ weapondata_throwable_t weapon_m61grenade =
BOOL weapon_grenade_onInputPress(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
void weapon_grenade_onInputPress(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
if(arg_thisWeapon.iCount == 0){
// what. how.
@ -302,7 +302,7 @@ BOOL weapon_grenade_onInputPress(player pl, weapondynamic_t arg_thisWeapon, int
}
}
return TRUE;
return;
}
@ -315,7 +315,7 @@ BOOL weapon_grenade_onInputPress(player pl, weapondynamic_t arg_thisWeapon, int
// It makes far more sense to just check for either input still being held-down in the think
// method during the pullpin grenade phase.
/*
BOOLEAN weapon_grenade_onInputRelease(player pl, weapondynamic_t arg_thisWeapon){
void weapon_grenade_onInputRelease(player pl, weapondynamic_t arg_thisWeapon){
if(pl.w_attack_next > 0){
// wait for w_attack_next to expire before doing logic against grenadeFireIndex choice
// (except above, checks a bit differently for spawning the grenade)

View file

@ -41,7 +41,6 @@ void weapon_miniuzi_akimbo_onColdCock(player pl, weapondynamic_t arg_thisWeapon)
}
//weapondata_ironsight_t weapon_miniuzi_akimbo =
weapondata_gun_t weapon_miniuzi_akimbo =
{
WEAPONDATA_TYPEID_GUN,
@ -79,18 +78,7 @@ weapondata_gun_t weapon_miniuzi_akimbo =
1,
-1,
-1,
-1/*,
{
weaponseq_miniuzi_akimbo::change,
21.0f/60.0f,
weaponseq_miniuzi_akimbo::rechange,
21.0f/60.0f,
weaponseq_miniuzi_akimbo::idleb,
weaponseq_miniuzi_akimbo::reloadb,
76.0f/30.0f,
{0.030000, 2.000000, 0.005000}
}
*/
-1
};
@ -150,15 +138,13 @@ w_miniuzi_akimbo_holster(void)
}
// General attack method to be called by primary or secondary fire as needed.
// The firemode used determines whether only pressing primary fire works (alternate b/w
// the Akimbo weapons with each shot), or primary & secondary control the left/right
// Akimbo weapons consistently.
// Putting it here avoids duplicating a bunch of code.
// Also, "attackTypeUsed" is whether primary (FALSE) or secondary (TRUE) lead to this point.
BOOLEAN weapon_miniuzi_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
void weapon_miniuzi_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
float randomChoice;
int finalAkimboChoice = BITS_AKIMBOCHOICE_NONE; //default
@ -172,11 +158,9 @@ BOOLEAN weapon_miniuzi_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon,
//because I am not copy/pasting this monstrosity 5 times.
finalAkimboChoice = weapon_akimbo_fullAttackChoice(pl, ary_weaponData[WEAPON_ID::MINIUZI_AKIMBO], arg_thisWeapon, attackTypeUsed);
SAVE_STATE(pl.nextAkimboAttackPreference);
if(finalAkimboChoice == -1){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
/*
@ -193,13 +177,13 @@ BOOLEAN weapon_miniuzi_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon,
if((finalAkimboChoice & BITS_AKIMBOCHOICE_RIGHT)){
PLAY_CLICK_SOUND_RIGHT
}
return FALSE;
return;
}
// ?? Is this even possible?
if(finalAkimboChoice == 0){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
@ -279,23 +263,13 @@ BOOLEAN weapon_miniuzi_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon,
weapon_base_setWholeAttackDelay(pl, (*ary_weaponData[pl.activeweapon]).fAttackDelay * 1);
}
return TRUE;
}//END OF weapon_miniuzi_akimbo_attack
}// weapon_miniuzi_akimbo_attack
void
w_miniuzi_akimbo_primary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
pl.akimboTest = 0;
if(input_buttons & INPUT_BUTTON3){
weapon_miniuzi_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
}else{
weapon_miniuzi_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
}
weapon_gun_akimbo_full_primaryAttack(weapon_miniuzi_akimbo_attack);
}
@ -303,16 +277,7 @@ w_miniuzi_akimbo_primary(void)
void
w_miniuzi_akimbo_secondary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_FREE_FULL){
weapon_miniuzi_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
//pl.akimboFirePrev = BITS_AKIMBOCHOICE_RIGHT;
}
weapon_gun_akimbo_full_secondaryAttack(weapon_miniuzi_akimbo_attack);
}

View file

@ -276,7 +276,7 @@ w_mossberg500_secondary(void)
}
*/
return weapon_ironsight_ToggleIronsight(pl, (weapondata_ironsight_t*)ary_weaponData[WEAPON_ID::MOSSBERG500], arg_thisWeapon);
weapon_ironsight_ToggleIronsight(pl, (weapondata_ironsight_t*)ary_weaponData[WEAPON_ID::MOSSBERG500], arg_thisWeapon);
}

View file

@ -151,6 +151,15 @@ w_mp5k_primary(void)
INPUT_PRIMARY_TAP_GATE
}
if(
pl.aryNextBurstShotTime_listenIndex != -1 &&
arg_thisWeapon.iFireMode != BITS_FIREMODE_NONE
){
// the player is trying to manually fire while burst-fire is in the middle
// of sending shots? STOP
return;
}
if (!arg_thisWeapon.iClipLeft || WEAPON_UNDERWATER_CHECK) {
PLAY_CLICK_SOUND
return;
@ -185,7 +194,7 @@ w_mp5k_primary(void)
if(arg_thisWeapon.iFireMode == BITS_FIREMODE_BURST)
{
weapon_base_burstFire(pl, ary_weaponData[WEAPON_ID::MP5SD], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, 3, 0.02);
weapon_gun_burstFire(pl, (weapondata_gun_t*)ary_weaponData[WEAPON_ID::MP5SD], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, 3, 0.02, 0.18);
}
else if(arg_thisWeapon.iFireMode == BITS_FIREMODE_SEMI || arg_thisWeapon.iFireMode == BITS_FIREMODE_FULL)
{

View file

@ -135,6 +135,15 @@ w_mp5sd_primary(void)
INPUT_PRIMARY_TAP_GATE
}
if(
pl.aryNextBurstShotTime_listenIndex != -1 &&
arg_thisWeapon.iFireMode != BITS_FIREMODE_NONE
){
// the player is trying to manually fire while burst-fire is in the middle
// of sending shots? STOP
return;
}
if (!arg_thisWeapon.iClipLeft || WEAPON_UNDERWATER_CHECK) {
PLAY_CLICK_SOUND
return;
@ -160,7 +169,7 @@ w_mp5sd_primary(void)
if(arg_thisWeapon.iFireMode == BITS_FIREMODE_BURST)
{
weapon_base_burstFire(pl, ary_weaponData[WEAPON_ID::MP5SD], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, 3, 0.02);
weapon_gun_burstFire(pl, (weapondata_gun_t*)ary_weaponData[WEAPON_ID::MP5SD], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, 3, 0.02, 0.18);
}
else if(arg_thisWeapon.iFireMode == BITS_FIREMODE_SEMI || arg_thisWeapon.iFireMode == BITS_FIREMODE_FULL)
{

View file

@ -152,7 +152,7 @@ w_rugermk1_primary(void)
#ifdef CLIENT
View_ShowMuzzleflash(MUZZLE_SMALL);
View_AddEvent(w_ejectshell_pistol, 0.0f);
//View_AddEvent(w_ejectshell_pistol, 0.0f);
#endif
weapon_base_onAttack(pl, ary_weaponData[WEAPON_ID::RUGERMK1], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);

View file

@ -193,6 +193,7 @@ w_sawedoff_primary(void)
TS_Weapons_ViewAnimation(weaponseq_sawedoff::shoot2, 31.0f/33.0f);
}
}else{
randomChoice = random();
if(randomChoice < 0.5){
TS_Weapons_ViewAnimation(weaponseq_sawedoff::shoot1b, 31.0f/33.0f);
}else{
@ -202,7 +203,7 @@ w_sawedoff_primary(void)
#ifdef CLIENT
View_ShowMuzzleflash(MUZZLE_SMALL);
View_AddEvent(w_ejectshell_pistol, 0.0f);
//View_AddEvent(w_ejectshell_pistol, 0.0f);
#endif
weapon_base_onAttack(pl, ary_weaponData[WEAPON_ID::SAWEDOFF], arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
@ -223,7 +224,7 @@ w_sawedoff_secondary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
return weapon_ironsight_ToggleIronsight(pl, (weapondata_ironsight_t*)ary_weaponData[WEAPON_ID::SAWEDOFF], arg_thisWeapon);
weapon_ironsight_ToggleIronsight(pl, (weapondata_ironsight_t*)ary_weaponData[WEAPON_ID::SAWEDOFF], arg_thisWeapon);
}
// need custom reload logic, works more like a typical weapon
@ -240,14 +241,14 @@ w_sawedoff_reload(void)
// CHECK - we have two reload anims for ordinary and ironsight mode each.
// One for if we have 1 clip left, another for if we have 0 clip left.
if(arg_thisWeapon.iClipLeft == 0){
//do the both-empty reload anim.
// do the both-empty reload anim.
if(!arg_thisWeapon.iIronSight){
reloadSeq = weaponseq_sawedoff::reload;
}else{
reloadSeq = weaponseq_sawedoff::reloadb;
}
}else{
//wasn't 0? must be 1. Otherwise we wouldn't have reached this point.
// wasn't 0? must be 1. Otherwise we wouldn't have reached this point.
if(!arg_thisWeapon.iIronSight){
reloadSeq = weaponseq_sawedoff::reload_sigle;
}else{

View file

@ -119,7 +119,7 @@ w_skorpion_akimbo_holster(void)
// Akimbo weapons consistently.
// Putting it here avoids duplicating a bunch of code.
// Also, "attackTypeUsed" is whether primary (FALSE) or secondary (TRUE) lead to this point.
BOOLEAN weapon_skorpion_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
void weapon_skorpion_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
float randomChoice;
int finalAkimboChoice = BITS_AKIMBOCHOICE_NONE; //default
@ -133,11 +133,9 @@ BOOLEAN weapon_skorpion_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon,
//because I am not copy/pasting this monstrosity 5 times.
finalAkimboChoice = weapon_akimbo_fullAttackChoice(pl, ary_weaponData[WEAPON_ID::SKORPION_AKIMBO], arg_thisWeapon, attackTypeUsed);
SAVE_STATE(pl.nextAkimboAttackPreference);
if(finalAkimboChoice == -1){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
/*
@ -154,13 +152,13 @@ BOOLEAN weapon_skorpion_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon,
if((finalAkimboChoice & BITS_AKIMBOCHOICE_RIGHT)){
PLAY_CLICK_SOUND_RIGHT
}
return FALSE;
return;
}
// ?? Is this even possible?
if(finalAkimboChoice == 0){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
@ -224,23 +222,13 @@ BOOLEAN weapon_skorpion_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon,
weapon_base_setWholeAttackDelay(pl, (*ary_weaponData[pl.activeweapon]).fAttackDelay * 1);
}
return TRUE;
}//END OF weapon_skorpion_akimbo_attack
}// weapon_skorpion_akimbo_attack
void
w_skorpion_akimbo_primary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
pl.akimboTest = 0;
if(input_buttons & INPUT_BUTTON3){
weapon_skorpion_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
}else{
weapon_skorpion_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
}
weapon_gun_akimbo_full_primaryAttack(weapon_skorpion_akimbo_attack);
}
@ -248,16 +236,7 @@ w_skorpion_akimbo_primary(void)
void
w_skorpion_akimbo_secondary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_FREE_FULL){
weapon_skorpion_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
//pl.akimboFirePrev = BITS_AKIMBOCHOICE_RIGHT;
}
weapon_gun_akimbo_full_secondaryAttack(weapon_skorpion_akimbo_attack);
}

View file

@ -152,7 +152,7 @@ var int rightCount = 0;
// Akimbo weapons consistently.
// Putting it here avoids duplicating a bunch of code.
// Also, "attackTypeUsed" is whether primary (FALSE) or secondary (TRUE) lead to this point.
BOOLEAN weapon_socommk23_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
void weapon_socommk23_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon, int attackTypeUsed){
//weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
//special case
@ -168,13 +168,10 @@ BOOLEAN weapon_socommk23_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon
// because I am not copy/pasting this monstrosity 5 times.
finalAkimboChoice = weapon_akimbo_semiAttackChoice(pl, ary_weaponData[WEAPON_ID::SOCOMMK23_AKIMBO], arg_thisWeapon, attackTypeUsed);
#ifdef CLIENT
SAVE_STATE(pl.nextAkimboAttackPreference);
#endif
if(finalAkimboChoice == -1){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
@ -191,17 +188,15 @@ BOOLEAN weapon_socommk23_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon
if((finalAkimboChoice & BITS_AKIMBOCHOICE_RIGHT)){
PLAY_CLICK_SOUND_RIGHT
}
return FALSE;
return;
}
// ?? Is this even possible?
if(finalAkimboChoice == 0){
//pl.akimboFirePrev = 0;
return FALSE;
return;
}
// DEBUG!!!
if((finalAkimboChoice & BITS_AKIMBOCHOICE_LEFT)){
leftCount++;
@ -315,65 +310,20 @@ BOOLEAN weapon_socommk23_akimbo_attack(player pl, weapondynamic_t arg_thisWeapon
weapon_base_setWholeAttackDelay(pl, (*ary_weaponData[pl.activeweapon]).fAttackDelay * 1);
}
return TRUE;
}//END OF weapon_socommk23_akimbo_attack
}// weapon_socommk23_akimbo_attack
void
w_socommk23_akimbo_primary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
// in addition to the primary input, which lead to '_primary' being called at all.
if(input_buttons & INPUT_BUTTON3){
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH, &weapon_socommk23_akimbo_attack)){
// nothing unusual here.
pl.akimboTest = 0;
weapon_socommk23_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_BOTH);
}else{
}
}else{
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT, &weapon_socommk23_akimbo_attack)){
weapon_socommk23_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT);
pl.akimboFirePrev = BITS_AKIMBOCHOICE_LEFT;
}
}
weapon_gun_akimbo_semi_primaryAttack(weapon_socommk23_akimbo_attack);
}
void
w_socommk23_akimbo_secondary(void)
{
player pl = (player)self;
weapondynamic_t arg_thisWeapon = pl.ary_myWeapons[pl.inventoryEquippedIndex];
// reset
pl.akimboTest = 0;
// NOTE - holding primary is impossible, would've called _primary above if so.
// Only secondary could possibly be held (and, is).
if(arg_thisWeapon.iFireModeAkimbo == BITS_FIREMODE_AKIMBO_SEMI_AUTO){
// since secondary fire does nothing in semi-auto, we let it do ironsight stuff here
weapon_ironsight_ToggleIronsight(pl, (weapondata_ironsight_t*)ary_weaponData[WEAPON_ID::SOCOMMK23_AKIMBO], arg_thisWeapon);
}else{
// fires the right weapon always
//weapon_socommk23_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
//return;
if(!weapon_akimbo_semiAttackDualHack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_LEFT, &weapon_socommk23_akimbo_attack)){
weapon_socommk23_akimbo_attack(pl, arg_thisWeapon, BITS_AKIMBOCHOICE_RIGHT);
pl.akimboFirePrev = BITS_AKIMBOCHOICE_RIGHT;
}
}
weapon_ironsight_akimbo_semi_secondaryAttack(weapon_socommk23_akimbo_attack, WEAPON_ID::SOCOMMK23_AKIMBO);
}