nuclearsilo583 / zephyrus-store-preview-new-syntax

My rewritten zephyrus store
61 stars 40 forks source link

add store_item_parachute.sp #85

Closed oqyh closed 4 months ago

oqyh commented 2 years ago
/*
 * Parachutes for Zephyrus store
 * by: shanapu
 * https://github.com/shanapu/StoreParachute/
 * 
 * used code by zipcore
 * https://gitlab.com/Zipcore/HungerGames/blob/master/addons/sourcemod/scripting/hungergames/tools/parachute.sp
 * 
 * Copyright (C) 2018 Thomas Schmidt (shanapu)
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, version 3.0, as published by the
 * Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */

/******************************************************************************
                   STARTUP
******************************************************************************/

// Includes
#include <sourcemod>
#include <sdktools>
#include <store>
#include <smartdm>

#pragma semicolon 1
#pragma newdecls required

bool g_bParachute[MAXPLAYERS+1];
bool g_bItem[MAXPLAYERS+1] = false;

char g_sModels[STORE_MAX_ITEMS][PLATFORM_MAX_PATH];

float g_fSpeed[STORE_MAX_ITEMS];

int g_iModelCount = 0;
int g_iVelocity = -1;
int g_iParaEntRef[MAXPLAYERS+1] = {INVALID_ENT_REFERENCE, ...};
int g_iClientModel[MAXPLAYERS+1];

public Plugin myinfo = {
    name = "Parachute for Zephyrus Store",
    author = "shanapu",
    description = "Adds support for parachutes to Zephyrus Store plugin",
    version = "1.2",
    url = "https://github.com/shanapu/StoreParachute"
};

public void OnPluginStart()
{
    Store_RegisterHandler("parachute", "", ParaChute_OnMapStart, ParaChute_Reset, ParaChute_Config, ParaChute_Equip, ParaChute_Remove, true);

    g_iVelocity = FindSendPropInfo("CBasePlayer", "m_vecVelocity[0]");
}

public void ParaChute_OnMapStart()
{
    for(int i = 0; i < g_iModelCount; ++i)
    {
        Downloader_AddFileToDownloadsTable(g_sModels[i]);

        if (IsModelPrecached(g_sModels[i]))
            continue;

        PrecacheModel(g_sModels[i]);
    }
}

public void ParaChute_Reset()
{
    g_iModelCount = 0;
}

public bool ParaChute_Config(Handle &kv, int itemid)
{
    Store_SetDataIndex(itemid, g_iModelCount);

    KvGetString(kv, "model", g_sModels[g_iModelCount], PLATFORM_MAX_PATH);
    g_fSpeed[g_iModelCount] = KvGetFloat(kv, "fallspeed", 100.0);

    if (!FileExists(g_sModels[g_iModelCount], true))
        return false;

    g_iModelCount++;

    return true;
}

public int ParaChute_Equip(int client, int id)
{
    g_iClientModel[client] = Store_GetDataIndex(id);
    g_bItem[client] = true;

    return -1;
}

public int ParaChute_Remove(int client)
{
    DisableParachute(client);
    g_bItem[client] = false;

    return 0;
}

public void OnClientDisconnect(int client)
{
    g_bItem[client] = false;
}

public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2])
{
    if (!g_bItem[client])
        return Plugin_Continue;

    // https://gitlab.com/Zipcore/HungerGames/blob/master/addons/sourcemod/scripting/hungergames/tools/parachute.sp
    // Check abort reasons
    if(g_bParachute[client])
    {
        // Abort by released button
        if(!(buttons & IN_USE) || !IsPlayerAlive(client))
        {
            DisableParachute(client);
            return Plugin_Continue;
        }

        // Abort by up speed
        float fVel[3];
        GetEntDataVector(client, g_iVelocity, fVel);

        if(fVel[2] >= 0.0)
        {
            DisableParachute(client);
            return Plugin_Continue;
        }

        // Abort by on ground flag
        if(GetEntityFlags(client) & FL_ONGROUND)
        {
            DisableParachute(client);
            return Plugin_Continue;
        }

        // decrease fallspeed
        float fOldSpeed = fVel[2];

        // Player is falling to fast, lets slow him to max gc_fSpeed
        if(fVel[2] < g_fSpeed[g_iClientModel[client]] * (-1.0))
        {
            fVel[2] = g_fSpeed[g_iClientModel[client]] * (-1.0);
        }

        // fallspeed changed
        if(fOldSpeed != fVel[2])
            TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, fVel);
    }
    // Should we start the parashute?
    else if(g_bItem[client])
    {
        // Reject by released button
        if(!(buttons & IN_USE) || !IsPlayerAlive(client))
            return Plugin_Continue;

        // Reject by on ground flag
        if(GetEntityFlags(client) & FL_ONGROUND)
            return Plugin_Continue;

        // Reject by up speed
        float fVel[3];
        GetEntDataVector(client, g_iVelocity, fVel);

        if(fVel[2] >= 0.0)
            return Plugin_Continue;

        // Open parachute
        int iEntity = CreateEntityByName("prop_dynamic_override");
        DispatchKeyValue(iEntity, "model", g_sModels[g_iClientModel[client]]);
        DispatchSpawn(iEntity);

        SetEntityMoveType(iEntity, MOVETYPE_NOCLIP);

        // Teleport to player
        float fPos[3];
        float fAng[3];
        GetClientAbsOrigin(client, fPos);
        GetClientAbsAngles(client, fAng);
        fAng[0] = 0.0;
        TeleportEntity(iEntity, fPos, fAng, NULL_VECTOR);

        // Parent to player
        char sClient[16];
        Format(sClient, 16, "client%d", client);
        DispatchKeyValue(client, "targetname", sClient);
        SetVariantString(sClient);
        AcceptEntityInput(iEntity, "SetParent", iEntity, iEntity, 0);

        g_iParaEntRef[client] = EntIndexToEntRef(iEntity);
        g_bParachute[client] = true;
    }

    return Plugin_Continue;
}

void DisableParachute(int client)
{
    int iEntity = EntRefToEntIndex(g_iParaEntRef[client]);
    if(iEntity != INVALID_ENT_REFERENCE)
    {
        AcceptEntityInput(iEntity, "ClearParent");
        AcceptEntityInput(iEntity, "kill");
    }

    g_bParachute[client] = false;
    g_iParaEntRef[client] = INVALID_ENT_REFERENCE;
}
nuclearsilo583 commented 2 years ago

Please fork this repo and open this module as PR