#include <zombiereloaded>
#include <sourcemod>
#include <sdktools>
#include <colorvariables>
#include <chat-processor>
//#include <morecolors.inc>
#pragma semicolon 1
#pragma newdecls required
 
public Plugin myinfo =
{
    name        = "Meteors",
    author      = "Neon",
    description = "",
    version     = "Meteors",
    url         = "https://steamcommunity.com/id/n3ontm"
}
 
//ambient/explosions/explode_9.wav
//models/effects/vol_light128x512.mdl
 
bool g_bEnabled = false;
 
public void OnPluginStart()
{  
    HookEvent("round_end", OnRoundEnding);
    RegAdminCmd("sm_meteors", Command_Meteors, ADMFLAG_GENERIC);
}
 
public void OnMapStart()
{
    g_bEnabled = false;
    PrecacheModel("models/props/cs_office/vending_machine.mdl");
    
    CreateTimer(5.0, MeteorMain, INVALID_HANDLE, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE);
}
 
public void OnRoundEnding(Event hEvent, const char[] sEvent, bool bDontBroadcast)
{
    g_bEnabled = false;
}
 
public Action Command_Meteors(int client, int args)
{
    if (g_bEnabled)
    {
        g_bEnabled = false;
        CPrintToChatAll("{orchid}[Meteors] {Green}%N has disabled Meteors!", client);
    }
    else if (!(g_bEnabled))
    {  
        g_bEnabled = true;
        CPrintToChatAll("{orchid}[Meteors] {Green}%N has enabled Meteors!", client);
    }    
}
 
public Action MeteorMain(Handle timer)
{
    if (!(g_bEnabled))
    {
        return;
    }
    int victimClient = GetTargetClient();
   
    if (victimClient == -1)
    {
        return;    
    }
    int indicator = SpawnIndicator(victimClient);  
    int model = SpawnMeteor2(victimClient);
    int hurt = SpawnTriggerHurt(victimClient);
    int move = SpawnMoveLinear(victimClient);  
    int explosion = SpawnExplosion(victimClient);  
    int sound = SpawnAmbientGeneric(victimClient);
    int particle = SpawnParticle(victimClient);
    int particle2 = SpawnParticle(victimClient);   
   
    SetVariantString("!activator");
    AcceptEntityInput(model, "SetParent", move);
   
    SetVariantString("!activator");
    AcceptEntityInput(hurt, "SetParent", move);
   
    SetVariantString("!activator");
    AcceptEntityInput(particle, "SetParent", move);
   
    SetVariantString("!activator");
    AcceptEntityInput(particle2, "SetParent", move);
   
    AcceptEntityInput(move, "Open");
}
 
public Action SpawnParticle(int client)
{
    int Entity;
    // Spawn dynamic prop entity
    if ((Entity = CreateEntityByName("info_particle_system")) == INVALID_ENT_REFERENCE)
        return -1;
   
    // Generate unique id for the entity
    char StrEntityName[64]; 
    Format(StrEntityName, sizeof(StrEntityName), "info_particle_system_%i", Entity);
   
    // Setup entity
    DispatchKeyValue(Entity, "targetname", "meteor_particle");
    DispatchKeyValue(Entity, "effect_name", "fire_large_01");
    //DispatchKeyValue(Entity, "effect_name", "burning_fx");
    DispatchSpawn(Entity);
    ActivateEntity(Entity);
    AcceptEntityInput(Entity, "start");
   
    float fVector[3];
    float fAngles[3];
    GetClientAbsOrigin(client, fVector);
    GetClientAbsAngles(client, fAngles);
   
    fVector[2] += 7000.0;
   
    TeleportEntity(Entity, fVector, NULL_VECTOR, NULL_VECTOR);
   
    return Entity;
   
}
 
public Action SpawnAmbientGeneric(int client)
{
    int Entity;
   
    // Spawn dynamic prop entity
    if ((Entity = CreateEntityByName("ambient_generic")) == INVALID_ENT_REFERENCE)
        return -1;
   
    // Generate unique id for the entity
    char StrEntityName[64]; 
    Format(StrEntityName, sizeof(StrEntityName), "ambient_generic_%i", Entity);
   
    // Setup entity
    DispatchKeyValue(Entity, "targetname", "meteor_sound");
    DispatchKeyValue(Entity, "spawnflags", "48");
    DispatchKeyValue(Entity, "SourceEntityName", "meteor_model2");
    DispatchKeyValue(Entity, "radius", "3050");
    DispatchKeyValue(Entity, "message", "ambient/explosions/explode_9.wav");
    DispatchKeyValue(Entity, "volume", "10");
    DispatchKeyValue(Entity, "health", "10");
    DispatchKeyValue(Entity, "preset", "0");
    DispatchKeyValue(Entity, "pitch", "100");
    DispatchKeyValue(Entity, "pitchstart", "100"); 
    DispatchSpawn(Entity);
    ActivateEntity(Entity);
   
    return Entity;
}
 
public Action SpawnTriggerHurt(int client)
{
    int Entity;
   
    // Spawn dynamic prop entity
    if ((Entity = CreateEntityByName("trigger_hurt")) == INVALID_ENT_REFERENCE)
        return -1;
   
    // Generate unique id for the entity
    char StrEntityName[64]; 
    Format(StrEntityName, sizeof(StrEntityName), "trigger_hurt_%i", Entity);
   
    float fVector[3];
    float fAngles[3];
    GetClientAbsOrigin(client, fVector);
    GetClientAbsAngles(client, fAngles);
   
    fVector[2] += 7000.0;
   
   
    // Setup entity
    DispatchKeyValue(Entity, "targetname", "meteor_hurt");
    DispatchKeyValue(Entity, "spawnflags", "1");
    DispatchKeyValue(Entity, "StartDisabled", "0");
    DispatchKeyValueVector(Entity, "origin", fVector);
    DispatchKeyValue(Entity, "nodmgforce", "0");
    DispatchKeyValue(Entity, "damage", "80");
    //DispatchKeyValue(Entity, "damage", "320");
    DispatchKeyValue(Entity, "damagetype", "128");     
    DispatchKeyValue(Entity, "damagemodel", "0");  
    DispatchSpawn(Entity);
    ActivateEntity(Entity);
   
    SetEntityModel(Entity, "models/props/cs_office/vending_machine.mdl");
   
    float minbounds[3] = {-50.0, -50.0, -100.0};
    float maxbounds[3] = {50.0, 50.0, 100.0};
    SetEntPropVector(Entity, Prop_Send, "m_vecMins", minbounds);
    SetEntPropVector(Entity, Prop_Send, "m_vecMaxs", maxbounds);
   
    SetEntProp(Entity, Prop_Send, "m_nSolidType", 2);
 
    int enteffects = GetEntProp(Entity, Prop_Send, "m_fEffects");
    enteffects |= 32;
    SetEntProp(Entity, Prop_Send, "m_fEffects", enteffects);  
   
    return Entity;
}
 
public Action SpawnMeteor2(int client)
{
    int Entity;
    // Spawn dynamic prop entity
    if ((Entity = CreateEntityByName("prop_physics_multiplayer")) == INVALID_ENT_REFERENCE)
    {
        return -1;
    }
    // Generate unique id for the entity
	char StrEntityName[512];    
    Format(StrEntityName, sizeof(StrEntityName), "prop_physics_multiplayer_%i", Entity);
   
    // Setup entity
    DispatchKeyValue(Entity, "targetname", "meteor_model2");
    DispatchKeyValue(Entity, "model",      "models/props/cs_militia/militiarock05.mdl");
    DispatchKeyValue(Entity, "spawnflags",      "8");
    DispatchKeyValue(Entity, "pressuredelay",      "0");
    DispatchKeyValue(Entity, "physicsmode",      "2");
    DispatchKeyValue(Entity, "physdamagescale",      "0.1");
    DispatchKeyValue(Entity, "modelscale",      "2.0");
    DispatchSpawn(Entity);
   
    float fVector[3];
    float fAngles[3];
    GetClientAbsOrigin(client, fVector);
    GetClientAbsAngles(client, fAngles);
   
    fVector[2] += 7000.0;  
    //fVector[1] += 1000.0;
   
    TeleportEntity(Entity, fVector, NULL_VECTOR, NULL_VECTOR);
   
    return Entity;
   
}
public Action SpawnExplosion(int client)
{
    int Entity;
    // Spawn dynamic prop entity
    if ((Entity = CreateEntityByName("env_explosion")) == INVALID_ENT_REFERENCE)
        return -1;
   
    // Generate unique id for the entity
    char StrEntityName[64]; 
    Format(StrEntityName, sizeof(StrEntityName), "env_explosion_%i", Entity);
   
    // Setup entity
    DispatchKeyValue(Entity, "targetname", "meteor_explosion");
    DispatchKeyValue(Entity, "fireballsprite",      "sprites/zerogxplode.spr");
    DispatchKeyValue(Entity, "rendermode",      "5");
    DispatchKeyValue(Entity, "iMagnitude",      "300");
    DispatchKeyValue(Entity, "iRadiusOverride", "70"); 
 
    DispatchKeyValue(Entity, "spawnflags",      "81"); 
 
    DispatchSpawn(Entity);
   
    float fVector[3];
    float fAngles[3];
    GetClientAbsOrigin(client, fVector);
    GetClientAbsAngles(client, fAngles);
   
    TeleportEntity(Entity, fVector, NULL_VECTOR, NULL_VECTOR);
   
    return Entity;
   
   
}
 
public Action SpawnMeteor(int client)
{
    int Entity;
    // Spawn dynamic prop entity
    if ((Entity = CreateEntityByName("prop_dynamic")) == INVALID_ENT_REFERENCE)
        return -1;
   
    // Generate unique id for the entity
    char StrEntityName[64]; Format(StrEntityName, sizeof(StrEntityName), "prop_dynamic_%i", Entity);
   
    // Setup entity
    DispatchKeyValue(Entity, "targetname", "meteor_model");
    DispatchKeyValue(Entity, "model",      "models/props/cs_militia/militiarock05.mdl");
    DispatchKeyValue(Entity, "solid",      "0");
    DispatchKeyValue(Entity, "modelscale",      "1.0");
    DispatchKeyValue(Entity, "renderamt",      "255");
    DispatchKeyValue(Entity, "rendercolor",      "0 181 240");
    DispatchKeyValue(Entity, "renderfx",      "0");
    DispatchKeyValue(Entity, "rendermode",      "0");
 
    DispatchSpawn(Entity);
   
    float fVector[3];
    float fAngles[3];
    GetClientAbsOrigin(client, fVector);
    GetClientAbsAngles(client, fAngles);
   
    fVector[2] += 7000.0;  
    //fVector[1] += 1000.0;
   
    TeleportEntity(Entity, fVector, NULL_VECTOR, NULL_VECTOR);
   
    return Entity;
   
   
}
 
public Action SpawnMoveLinear(int client)
{
    int Entity;
    // Spawn dynamic prop entity
    if ((Entity = CreateEntityByName("func_movelinear")) == INVALID_ENT_REFERENCE)
        return -1;
   
    // Generate unique id for the entity
    char StrEntityName[64]; Format(StrEntityName, sizeof(StrEntityName), "func_movelinear_%i", Entity);
   
    float fVectorClient[3];
    float fVectorStart[3];
    float fAngles[3];
    float fVectorCalculated[3];
    float fAnglesCalculated[3];
    GetClientAbsOrigin(client, fVectorClient);
    GetClientAbsAngles(client, fAngles);
   
    fVectorStart = fVectorClient;
    fVectorStart[2] += 7000.0; 
   
    SubtractVectors(fVectorClient, fVectorStart, fVectorCalculated);
    float distanceF = GetVectorLength(fVectorCalculated, false);
    distanceF -= 128.0;
    NormalizeVector(fVectorCalculated, fVectorCalculated);
    GetVectorAngles(fVectorCalculated, fAnglesCalculated);  
   
    // Setup entity
    DispatchKeyValue(Entity, "targetname", "meteor_linear");  
    DispatchKeyValueVector(Entity, "movedir", fAnglesCalculated);
    DispatchKeyValueVector(Entity, "origin", fVectorStart);
    DispatchKeyValue(Entity, "speed", "3000");
    DispatchKeyValueFloat(Entity, "movedistance", distanceF);  
    DispatchKeyValue(Entity, "spawnflags", "8");
    DispatchKeyValue(Entity, "rendermode", "3");
    DispatchKeyValue(Entity, "rendercolor", "136 0 0");
    DispatchKeyValue(Entity, "OnFullyOpen", "!self,KillHierarchy,,0.01,1");
    DispatchKeyValue(Entity, "OnFullyOpen", "meteor_indicator,Kill,,0,1");
    DispatchKeyValue(Entity, "OnFullyOpen", "meteor_explosion,Explode,,0,1");
    DispatchKeyValue(Entity, "OnFullyOpen", "meteor_explosion,Kill,,0.01,1");
    DispatchKeyValue(Entity, "OnFullyOpen", "meteor_sound,PlaySound,,0,1");
    DispatchKeyValue(Entity, "OnFullyOpen", "meteor_sound,Kill,,0.01,1");
    DispatchSpawn(Entity);
   
    return Entity;
}
 
 
public Action SpawnIndicator(int client)
{
    int Entity;
    // Spawn dynamic prop entity
    if ((Entity = CreateEntityByName("prop_dynamic")) == INVALID_ENT_REFERENCE)
        return -1;
   
    // Generate unique id for the entity
    char StrEntityName[64]; 
    Format(StrEntityName, sizeof(StrEntityName), "prop_dynamic_%i", Entity);
   
    // Setup entity
    //this is problematic one
    DispatchKeyValue(Entity, "targetname", "meteor_indicator");
    DispatchKeyValue(Entity, "model",      "models/editor/spot_cone.mdl");
    DispatchKeyValue(Entity, "solid",      "0");
    DispatchKeyValue(Entity, "modelscale",      "5.5");
    DispatchKeyValue(Entity, "angles",      "0 0 90");
    DispatchKeyValue(Entity, "renderamt",      "255");
    DispatchKeyValue(Entity, "rendercolor",      "255 0 0");
    DispatchKeyValue(Entity, "renderfx",      "0");
    DispatchKeyValue(Entity, "rendermode",      "0");
 
    DispatchSpawn(Entity);
   
    float fVector[3];
    float fAngles[3];
    GetClientAbsOrigin(client, fVector);
    GetClientAbsAngles(client, fAngles);
   
    fVector[2] += 35.0; 
   
    TeleportEntity(Entity, fVector, NULL_VECTOR, NULL_VECTOR);
   
    return Entity;
}
 
public int GetTargetClient()
{
       
    int outsideClientCount = 0;
 	int[] outsideClients = new int[MaxClients];
   
    for(int i = 1; i <= MaxClients; i++)
    {
        if(IsClientInGame(i) && IsPlayerAlive(i) && (ZR_IsClientHuman(i)) && (GetClientDistanceToCeiling(i) > 200.0))
        {
            outsideClients[outsideClientCount] = i;
            outsideClientCount += 1;
        }
    }
   
    if (outsideClientCount == 0)
        return -1;
   
    int randomIndex = GetRandomInt(0, outsideClientCount - 1);
   
    return outsideClients[randomIndex];
 
}
 
public float GetClientDistanceToCeiling(int client)
{
    float distanceF = 0.0;
   
    float fOrigin[3];
    float fCeiling[3];
    GetClientAbsOrigin(client, fOrigin);
   
    fOrigin[2] += 10.0;
   
    TR_TraceRayFilter(fOrigin, {-90.0,0.0,0.0}, MASK_PLAYERSOLID, RayType_Infinite, TraceRayNoPlayers, client);
    if (TR_DidHit())
    {
        TR_GetEndPosition(fCeiling);
        fOrigin[2] -= 10.0;
        distanceF = GetVectorDistance(fOrigin, fCeiling);      
    }
    //PrintToChatAll("Client: %d - %f", client,distanceF);
    return distanceF;
}
 
public bool TraceRayNoPlayers(int entity, int mask, any data)
{
    if(entity == data || (entity >= 1 && entity <= MaxClients))
    {
        return false;
    }
    return true;
}