Custom Environment

Custom Environment 1.2

Нет прав для скачивания
Код:
/* AMXX Mod script.

    This plugin can change map environment to day/night/rain/snow/clean.

    Thanks to: KORD_12.7 and GordonFreeman for code, testing and suggestions.

    (c) Copyright 2013, AGHL.RU DevTeam
    This file is provided as is (no warranties).
*/

#pragma semicolon 1
#pragma ctrlchar '\'

#include <amxmodx>
#include <amxmisc>
#include <engine>
#include <fakemeta>
#include <fakemeta_util>
#include <hamsandwich>

#define AUTHOR "Lev"
#define PLUGIN "Custom Environment"
#define VERSION "1.2"

#define MAX_PLAYERS 32
#define MAX_RAINDRIPS 10
#define MAX_SNOWFLAKS 10

#define SND_SPAWNING        (1<<8)        // duplicated in protocol.h we're spawing, used in some cases for ambients
#define SND_STOP            (1<<5)        // duplicated in protocol.h stop sound
#define SND_CHANGE_VOL        (1<<6)        // duplicated in protocol.h change sound vol
#define SND_CHANGE_PITCH    (1<<7)        // duplicated in protocol.h change sound pitch

new const DEFAULT_DAY_SKY_NAME[] = "desert";
new const CLEAN_NIGHT_SKY_NAMES[][] = { "space", "night1" };
new const RAIN_DAY_SKY_NAMES[][] = { "doom1" };
new const RAIN_NIGHT_SKY_NAMES[][] = { "grimmnight" };
new const SHOW_DAY_SKY_NAMES[][] = { "snow", "snow1", "snowlake_", "blizzard256" };
new const SHOW_NIGHT_SKY_NAMES[][] = { "space", "night1" };

new const RAIN_SOUND[] = "ambience/rain2.wav";

new mapSkyName[32];
new pcvar_env_wind, pcvar_env_rain, pcvar_env_snow, pcvar_env_night, pcvar_env_lightning, pcvar_env_lights, pcvar_env_skyname, pcvar_sv_skyname;
new snowSprite, rainSprite, hazeSprite, splashSprite;
new taskEnt;
new bool:activePlayers[MAX_PLAYERS + 1];


public plugin_precache()
{
    pcvar_sv_skyname = get_cvar_pointer("sv_skyname");
    pcvar_env_skyname = register_cvar("env_skyname", "");

    pcvar_env_wind = register_cvar("env_wind", "0");
    pcvar_env_rain = register_cvar("env_rain", "0");
    pcvar_env_snow = register_cvar("env_snow", "0");
    pcvar_env_night = register_cvar("env_night", "0");
    pcvar_env_lightning = register_cvar("env_lightning", "0");
    pcvar_env_lights = register_cvar("env_lights", "");

    ExecuteConfigs();

    // Store sky name from the map
    get_pcvar_string(pcvar_sv_skyname, mapSkyName, charsmax(mapSkyName));

    // Update server skybox
    UpdateSky();

    // Precache the sky for client download
    new skyName[32];
    get_pcvar_string(pcvar_sv_skyname, skyName, charsmax(skyName));
    if (skyName[0])
        PrecacheSky(skyName);

    // Precache sprites
    snowSprite = precache_model("sprites/effects/snow8.spr");
    rainSprite = precache_model("sprites/effects/rain2.spr");
    hazeSprite = precache_model("sprites/effects/rainhaze.spr");
    splashSprite = precache_model("sprites/effects/wsplashf.spr");

    // Precache ambient sound
    precache_sound(RAIN_SOUND);
}

public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR);

    register_concmd("env_set", "SetGamma");
    register_concmd("day", "CmdLight", ADMIN_BAN, "- changes light to day");
    register_concmd("night", "CmdLight", ADMIN_BAN, "- changes light to night");
    register_concmd("clean", "CmdWeather", ADMIN_BAN, "- changes to clear weather");
    register_concmd("rain", "CmdWeather", ADMIN_BAN, "- changes to rainy weather");
    register_concmd("snow", "CmdWeather", ADMIN_BAN, "- changes to snowy weather");

    // Disable sky lighting so it doesn't mess with our custom lighting
    set_cvar_num("sv_skycolor_r", 0);
    set_cvar_num("sv_skycolor_g", 0);
    set_cvar_num("sv_skycolor_b", 0);

    // Create our think entity
    taskEnt = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"));
    set_pev(taskEnt, pev_classname, "weather_think");
    set_pev(taskEnt, pev_nextthink, get_gametime() + 0.5);    // Delayed start
    RegisterHamFromEntity(Ham_Think, taskEnt, "WeatherThink");
}

public plugin_end()
{
    set_pcvar_string(pcvar_sv_skyname, "");
}

ExecuteConfigs()
{
    new configFile[128], curMap[64], configDir[128];

    get_configsdir(configDir, charsmax(configDir));
    get_mapname(curMap, charsmax(curMap));

    formatex(configFile, charsmax(configFile), "%s/environment.cfg", configDir);
    if (file_exists(configFile))
        server_cmd("exec %s", configFile);

    new i = 0;
    while (curMap[i] != '_' && curMap[i++] != '\0') {/*do nothing*/}
    if (curMap[i]=='_')
    {
        // this map has a prefix
        curMap[i] = '\0';
        formatex(configFile, charsmax(configFile), "%s/maps/prefix_%s.cfg", configDir, curMap);
        if (file_exists(configFile))
            server_cmd("exec %s", configFile);
    }

    get_mapname(curMap, charsmax(curMap));
    formatex(configFile, charsmax(configFile), "%s/maps/%s.cfg", configDir, curMap);
    if (file_exists(configFile))
        server_cmd("exec %s", configFile);

    server_exec();
}

UpdateSky()
{
    new night = get_pcvar_num(pcvar_env_night);
    new rain = get_pcvar_num(pcvar_env_rain);
    new snow = get_pcvar_num(pcvar_env_snow);

    new skyName[32];
    get_pcvar_string(pcvar_env_skyname, skyName, charsmax(skyName));

    if (skyName[0])
        set_pcvar_string(pcvar_sv_skyname, skyName);
    else if (night && rain)
        set_pcvar_string(pcvar_sv_skyname, RAIN_NIGHT_SKY_NAMES[random_num(0, sizeof(RAIN_NIGHT_SKY_NAMES) - 1)]);
    else if (night && snow)
        set_pcvar_string(pcvar_sv_skyname, SHOW_NIGHT_SKY_NAMES[random_num(0, sizeof(SHOW_NIGHT_SKY_NAMES) - 1)]);
    else if (night)
        set_pcvar_string(pcvar_sv_skyname, CLEAN_NIGHT_SKY_NAMES[random_num(0, sizeof(CLEAN_NIGHT_SKY_NAMES) - 1)]);
    else if (rain)
        set_pcvar_string(pcvar_sv_skyname, RAIN_DAY_SKY_NAMES[random_num(0, sizeof(RAIN_DAY_SKY_NAMES) - 1)]);
    else if (snow)
        set_pcvar_string(pcvar_sv_skyname, SHOW_DAY_SKY_NAMES[random_num(0, sizeof(SHOW_DAY_SKY_NAMES) - 1)]);
    else if (mapSkyName[0])
        set_pcvar_string(pcvar_sv_skyname, mapSkyName);
    else
        set_pcvar_string(pcvar_sv_skyname, DEFAULT_DAY_SKY_NAME);
}

public client_putinserver(id)
{
    SetGamma();

    if (!is_user_bot(id) && !is_user_hltv(id))
        activePlayers[id] = true;

    if (get_pcvar_num(pcvar_env_rain))
        engfunc(EngFunc_EmitAmbientSound, taskEnt, {0, 0, 0}, RAIN_SOUND, 1.0, ATTN_NONE, SND_CHANGE_VOL, 100);

}

public client_disconnect(id)
{
    if (!is_user_bot(id) && !is_user_hltv(id))
        activePlayers[id] = false;
}

public SetGamma()
{
    new lightPattern[32];
    get_pcvar_string(pcvar_env_lights, lightPattern, charsmax(lightPattern));
    if (lightPattern[0])
        set_lights(lightPattern);
    else if (get_pcvar_num(pcvar_env_night))
        set_lights("b");
    else
        set_lights("m");
}

public CmdLight(id, level, cid)
{
    if (!cmd_access(id, level, cid, 1))
        return PLUGIN_HANDLED;

    new cmd[10];
    read_argv(0, cmd, charsmax(cmd));
    if (equal(cmd, "day"))
    {
        set_pcvar_num(pcvar_env_night, 0);
        console_print(id, "Light set to day, change the map to change the sky.");
    }
    else if (equal(cmd, "night"))
    {
        set_pcvar_num(pcvar_env_night, 1);
        console_print(id, "Light set to night, change the map to change the sky.");
    }

    UpdateSky();
    SetGamma();

    return PLUGIN_HANDLED;
}

public CmdWeather(id, level, cid)
{
    if (!cmd_access(id, level, cid, 1))
        return PLUGIN_HANDLED;

    new cmd[10];
    read_argv(0, cmd, charsmax(cmd));
    if (equal(cmd, "clean"))
    {
        set_pcvar_num(pcvar_env_rain, 0);
        set_pcvar_num(pcvar_env_snow, 0);
        console_print(id, "Weather set to clear, change the map to change the sky.");
    }
    else if (equal(cmd, "rain"))
    {
        set_pcvar_num(pcvar_env_rain, MAX_RAINDRIPS);
        set_pcvar_num(pcvar_env_snow, 0);
        console_print(id, "Weather set to rainy, change the map to change the sky.");
    }
    else if (equal(cmd, "snow"))
    {
        set_pcvar_num(pcvar_env_rain, 0);
        set_pcvar_num(pcvar_env_snow, MAX_SNOWFLAKS);
        console_print(id, "Weather set to snowy, change the map to change the sky.");
    }

    UpdateSky();

    return PLUGIN_HANDLED;
}

public WeatherThink(ent)
{
    static Float:origin[3], Float:offset[3], Float:spawn[3], Float:end[3], Float:vel[3], Float:windVel[3];
    static content, i, c, maxi, maxc, id, u, l, sprite, life, bool:far, bool:windy;
    static wind, rain, snow, night, lightning, lastRain;

    if (ent != taskEnt)
        return;

    // Fetch cvar values
    if (u == 0)
    {
        wind = get_pcvar_num(pcvar_env_wind);
        rain = get_pcvar_num(pcvar_env_rain);
        snow = get_pcvar_num(pcvar_env_snow);
        night = get_pcvar_num(pcvar_env_night);
        lightning = get_pcvar_num(pcvar_env_lightning);

        clamp(wind, 0, 10);
        clamp(rain, 0, MAX_RAINDRIPS);
        clamp(snow, 0, MAX_SNOWFLAKS);

        // Rain have precedence like in CS
        if (rain && snow)
        {
            set_pcvar_num(pcvar_env_snow, 0);
            snow = 0;
        }

        // Ambient sounds
        if (!lastRain && rain)
        {
            engfunc(EngFunc_EmitAmbientSound, taskEnt, {0, 0, 0}, RAIN_SOUND, 1.0, ATTN_NONE, SND_CHANGE_VOL, 100);
            lastRain = rain;
        }
        else if (lastRain && !rain)
        {
            engfunc(EngFunc_EmitAmbientSound, taskEnt, {0, 0, 0}, RAIN_SOUND, 0.0, ATTN_NONE, SND_CHANGE_VOL, 100);
            lastRain = rain;
        }
    }
    u++;
    if (u > 20) u = 0;

    // Skip if weather is clear
    if (!rain && !snow)
    {
        set_pev(ent, pev_nextthink, get_gametime() + 1.0);
        return;
    }
    set_pev(ent, pev_nextthink, get_gametime() + 0.1);

    // Night rain lightning
    if (night && rain)
    {
        if (lightning && !l && random_num(0, 1000) <= 5)
        {
            set_lights(random_num(0, 1) < 1 ? "cbbbbbbbbbbbbbbbbbcccbbbbbbbbb" : "cccbbbbbbbbcbbbbbbccbbbbbbbbbb");
            l++;
        }
        else if (l)
        {
            l++;
            // Delay before setting back to night
            if (l == 120)
            {
                set_lights("b");
            }
            // Delay before new lightning can be fired
            else if (l > 500)
            {
                l = 0;
            }
        }
    }

    // Calculate wind
    if (wind)
    {
        windVel[0] += random_float(-1.0, 1.0) * wind;
        windVel[1] += random_float(-1.0, 1.0) * wind;
        windVel[0] = floatclamp(windVel[0], -40.0 * wind, 40.0 * wind);
        windVel[1] = floatclamp(windVel[1], -40.0 * wind, 40.0 * wind);
        windVel[2] = -(floatabs(windVel[0]) + floatabs(windVel[1]));
    }
    else
    {
        windVel[0] = 0.0;
        windVel[1] = 0.0;
        windVel[2] = 0.0;
    }
    windy = windVel[2] < -250.0;

    // Setup effect parameters
    if (rain)
    {
        maxc = rain;
        maxi = maxc * 4;
        vel[0] = random_float(-5.0, 5.0) + windVel[0] * 2.0;
        vel[1] = random_float(-5.0, 5.0) + windVel[1] * 2.0;
        vel[2] = random_float(-3500.0, -2500.0) - windVel[2];
        sprite = rainSprite;
        life = 1;
    }
    else // snow
    {
        maxc = snow / 2;
        maxi = maxc * 4;
        vel[0] = random_float(-20.0, 20.0) + windVel[0];
        vel[1] = random_float(-20.0, 20.0) + windVel[1];
        vel[2] = random_float(-300.0, -150.0) + windVel[2] / 2.0;
        sprite = snowSprite;
        life = !windy ? 6 : (windVel[2] > -450.0 ? 5 : 4);
    }

    for (id = 1; id < MAX_PLAYERS + 1; id++)
    {
        if (!activePlayers[id])
            continue;

        pev(id, pev_origin, origin);

        // Lets try 'maxi' times to create 'maxc' rain drips or snow flaks
        for (i = 0, c = 0; i < maxi && c < maxc; i++)
        {
            // Random point where rain drip or snow flak will spawn (around a player a bit higher)
            offset[0] = random_float(-1000.0, 1000.0);
            offset[1] = random_float(-1000.0, 1000.0);
            offset[2] = vector_length(offset);
            far = offset[2] > 700.0;
            offset[2] = rain
                            ? random_float(500.0, 800.0)
                            : (windy
                                    ? far ? -vel[2] : -vel[2] * 1.5 //random_float(400.0, far ? 500.0 : 800.0)
                                    : far ? -vel[2] * 1.5 : -vel[2] * 2.0); //random_float(300.0, far ? 400.0 : 700.0));
            spawn[0] = origin[0] + offset[0];
            spawn[1] = origin[1] + offset[1];
            spawn[2] = origin[2] + offset[2];

            // Check where we want to spawn
            content = engfunc(EngFunc_PointContents, spawn);
            if (content == CONTENTS_EMPTY)
            {
                // If empty point then search upward for the sky
                end[0] = spawn[0];
                end[1] = spawn[1];
                end[2] = spawn[2] + 99999.0;
                fm_trace_line(0, spawn, end, end);
                content = engfunc(EngFunc_PointContents, end);
                // Skip this point if not under the sky
                if (content != CONTENTS_SKY)
                    continue;
            }
            else if (content == CONTENTS_SKY || content == CONTENTS_SOLID)
            {
                // If solid or sky point then search down then upward for the sky
                end[0] = spawn[0];
                end[1] = spawn[1];
                end[2] = spawn[2] - 99999.0;
                fm_trace_line(0, spawn, end, end);
                fm_trace_line(0, end, spawn, spawn);
                content = engfunc(EngFunc_PointContents, spawn);
                // Skip this point if not under the sky
                if (content != CONTENTS_SKY)
                    continue;
            }
            else
                continue;
            // Lower a bit for the case if we are in the sky
            spawn[2] = spawn[2] - 10.0;

            // Reduce amount of live tempents at a time for a snow
            if (snow && far)
            {
                life = windy ? 2 : 3;
            }

            engfunc(EngFunc_MessageBegin, MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, spawn, id);
            {
                write_byte(TE_PROJECTILE);
                engfunc(EngFunc_WriteCoord, spawn[0]);        // position
                engfunc(EngFunc_WriteCoord, spawn[1]);
                engfunc(EngFunc_WriteCoord, spawn[2]);
                engfunc(EngFunc_WriteCoord, vel[0]);            // velocity
                engfunc(EngFunc_WriteCoord, vel[1]);
                engfunc(EngFunc_WriteCoord, vel[2]);
                write_short(sprite);    // sprite or model index
                write_byte(life);        // life
                write_byte(0);            // owner
            }
            message_end();

            // Additional effects for a rain
            if (rain)
            {
                // Find where drip will fall
                end[0] = spawn[0] + vel[0] * 100.0;
                end[1] = spawn[1] + vel[1] * 100.0;
                end[2] = spawn[2] + vel[2] * 100.0;
                fm_trace_line(0, spawn, end, end);
                // Move up a bit
                end[2] = end[2] + 1.0;

                // Only if near a player
                if (get_distance_f(origin, end) < 500.0)
                {
                    // Create a splash
                    engfunc(EngFunc_MessageBegin, MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, end, id);
                    {
                        write_byte(TE_SPRITE);
                        engfunc(EngFunc_WriteCoord, end[0]);        // position
                        engfunc(EngFunc_WriteCoord, end[1]);
                        engfunc(EngFunc_WriteCoord, end[2]);
                        write_short(splashSprite);    // sprite index
                        write_byte(9);                // scale in 0.1's
                        write_byte(100);            // brightness
                    }
                    message_end();

                    // Create a haze
                    engfunc(EngFunc_MessageBegin, MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, end, id);
                    {
                        write_byte(TE_SPRITE);
                        engfunc(EngFunc_WriteCoord, end[0]);        // position
                        engfunc(EngFunc_WriteCoord, end[1]);
                        engfunc(EngFunc_WriteCoord, end[2] + random_float(10.0, 30.0));
                        write_short(hazeSprite);            // sprite index
                        write_byte(random_num(5, 8));        // scale in 0.1's
                        write_byte(random_num(4, 8));        // brightness
                    }
                    message_end();
                }
            }

            // Iterate created effects
            c++;
        }
    }
}

/// Precache sky files for given name.
PrecacheSky(const skyName[])
{
    new buffer[128];
    new const prefixes[][] = { "bk.tga", "dn.tga", "ft.tga", "lf.tga", "rt.tga", "up.tga" };

    for (new i = 0; i < sizeof(prefixes); i++)
    {
        formatex(buffer, charsmax(buffer), "gfx/env/%s%s", skyName, prefixes[i]);
        precache_generic(buffer);
    }
}
Назад
Верх