View Single Post
DJPlaya
Senior Member
Join Date: Nov 2014
Location: Germany
Old 07-26-2015 , 09:01   Re: [TF2] (REQUEST) Dispensers shooting homing rockets
Reply With Quote #17

I know its old but maybe i can help someone with this
Made by Pelipoika
Quote:
Originally Posted by Arkarr View Post
Here is the source code (compille it). Again, I did nothing but posting this here. All credits goes to him.

Respect his wish, donate to sourcemod !

PHP Code:
#pragma semicolon 1

#include <sourcemod>
#include <sdktools>
#include <tf2_stocks>
#include <sdkhooks>

new Float:gf_RocketDamage     69.0;            //Rocket damage
new Float:gf_RocketDistance 2250000.0;    //See range of dispenser
new Float:gf_RocketSpeed     250.0;        //Speed of rocket

new MapStarted false;                        //Prevents a silly error from occuring with the AttachParticle stock

new Handle:hDisp INVALID_HANDLE;
new 
Handle:g_hArrayHoming;
new 
Handle:g_hCvarHomingSpeed;
new 
Handle:g_hCvarHomingReflect;

#define ARRAY_HOMING_SIZE 2

#define MDL_ROCKET    "models/props_mvm/mvm_human_skull.mdl"
#define SND_SHOOT    "mvm/giant_soldier/giant_soldier_rocket_shoot_crit.wav"

enum
{
    
ArrayHoming_EntityRef 0,
    
ArrayHoming_CurrentTarget
};

public 
Plugin:myinfo 
{
    
name "[TF2] Dispenser rockets V2",
    
author "Pelipoika",
    
description "Makes dispensers shoot homing rockets",
    
version "6.0",
    
url ""
}

public 
OnPluginStart()
{
    
hDisp CreateTimer(2.5timer_hDisp_,  TIMER_REPEAT);                //This controlls how often the dispenser  fires a rocket
    
g_hArrayHoming CreateArray(ARRAY_HOMING_SIZE);
    
g_hCvarHomingSpeed CreateConVar("sm_homing_speed""0.5""Speed multiplier for homing dsp rockets.");
    
g_hCvarHomingReflect CreateConVar("sm_homing_reflect""0.1""Speed multiplier increase for each reflection.");
}

public 
OnPluginEnd()
{
    if (
hDisp != INVALID_HANDLE)
    {
        
KillTimer(hDisp);
        
hDisp INVALID_HANDLE;
    }
}

public 
OnMapStart()
{
    
PrecacheModel(MDL_ROCKET);
    
PrecacheSound(SND_SHOOT);
    
    
MapStarted true;
}

public 
OnMapEnd()
{
    
MapStarted false;
}

public 
Action:timer_hDisp(Handle:timer)
{
    
Handle_DispenserRockets();
}

Handle_DispenserRockets()
{
    new 
index = -1;
    while ((
index FindEntityByClassname(index"obj_dispenser")) != -1//Loop through all the dispensers
    
{    
        
decl Float:playerpos[3], Float:targetvector[3], Float:dAng[3];
        new 
Float:dPos[3];
        new 
client GetEntPropEnt(indexProp_Send"m_hBuilder");
        new 
iAmmo GetEntProp(indexProp_Send"m_iAmmoMetal");
        new 
newiAmmo iAmmo -= 40;
        
        if(
IsValidClient(client))
        {
            new 
bossteam GetClientTeam(client);
            
            
decl playerarray[MAXPLAYERS+1];
            new 
playercount;
                
            new 
bool:disBuilding GetEntProp(indexProp_Send"m_bBuilding") == 1;
            new 
bool:disPlacing GetEntProp(indexProp_Send"m_bPlacing") == 1;
            new 
bool:disCarried GetEntProp(indexProp_Send"m_bCarried") == 1;
            
            
GetEntPropVector(indexProp_Send"m_vecOrigin"dPos);
            
//GetEntPropVector(index, Prop_Send, "m_angRotation", dAng);

            
if(!disBuilding && !disPlacing && !disCarried)
            {
                new 
disLevel GetEntProp(indexProp_Send"m_iHighestUpgradeLevel");
                if(
disLevel 2)         //This controls the level the dispenser has to be to be able to shoot rockets
                
{
                    
dPos[0] += 0.0;        //X        set the rocket's spawn position to the dispensers top
                    
dPos[1] += 0.0;        //Y
                    
dPos[2] += 64.0;    //Z
                        
                    
dAng[0] = 0.0;        //X        Makes sure the rocket is fired upwards
                    
dAng[1] = 0.0;        //Y
                    
dAng[2] = 95.0;        //Z

                    
TR_TraceRayFilter(dPosdAngMASK_SOLIDRayType_InfiniteTraceRayDontHitSelfclient);
                    
TR_GetEndPosition(targetvector);

                    for(new 
player 1player <= MaxClientsplayer++)
                    {
                        if(
player != client && IsClientInGame(player) && IsPlayerAlive(player))
                        {
                            if(
HomingProjectile_IsValidTarget(playerindexGetEntProp(indexProp_Send"m_iTeamNum")))
                            {
                                
GetClientEyePosition(playerplayerpos);
                                
playerpos[2] -= 30.0;
                                if(
GetVectorDistance(dPosplayerpos,  true) < gf_RocketDistance  && CanSeeTarget(dPosplayerpos,  playerbossteam))
                                {
                                    
playerarray[playercount] = player;    
                                    
playercount++;
                                }
                            }
                        }
                    }
                        
                    if(
playercount)    //As long as theres atleast 1 valid target fire a rocket
                    
{
                        if(
iAmmo >= 40)
                        {
                            
AttachParticle(index"ExplosionCore_sapperdestroyed"_64.08.0);
                            
EmitAmbientSound(SND_SHOOTdPosindex);
                            
SetEntProp(indexProp_Send"m_iAmmoMetal"newiAmmo);        //It costs 40 metal to shoot a rocket
                            
CreateProjectile(clientdPos);                                //Fire a rocket
                        
}
                    }
                }
            }
        }
    }
}

CreateProjectile(clientFloat:origin[3])    
{
    new 
entity CreateEntityByName("tf_projectile_rocket");
    if(
entity != -1)
    {
        
DispatchSpawn(entity);
    
        
SetEntProp(entityProp_Send"m_CollisionGroup"4);
        
SetEntProp(entityProp_Send"m_iTeamNum"GetClientTeam(client));
        
SetEntPropEnt(entityProp_Send"m_hOwnerEntity"client);            
        
SetEntPropVector(entityProp_Send"m_vecMins"Float:{0.0,0.0,0.0});    
        
SetEntPropVector(entityProp_Send"m_vecMaxs"Float:{0.0,0.0,0.0});
        
        new 
Float:vAngles[3];
        
vAngles[0] = -90.0;
        
vAngles[1] = 0.0;
        
vAngles[2] = 0.0;
        
        
decl Float:vVelocity[3];
        
decl Float:vBuffer[3];
        
        
GetAngleVectors(vAnglesvBufferNULL_VECTORNULL_VECTOR);
        
        
vVelocity[0] = vBuffer[0]*gf_RocketSpeed;
        
vVelocity[1] = vBuffer[1]*gf_RocketSpeed;
        
vVelocity[2] = vBuffer[2]*gf_RocketSpeed;
        
        
SetEntityModel(entityMDL_ROCKET);
        
SetEntProp(entityProp_Send"m_bCritical"true);
        
        
TeleportEntity(entityoriginvAnglesvVelocity);
        
        
SDKHook(entitySDKHook_StartTouchProjectileTouchHook);
        
CreateTimer(0.35Timer_CheckOwnershipEntIndexToEntRef(entity));
    }
}

public 
Action:Timer_CheckOwnership(Handle:hTimerany:iRef)
{
    new 
iProjectile EntRefToEntIndex(iRef);
    if(
iProjectile MaxClients && IsValidEntity(iProjectile))
    {
        new 
iLauncher GetEntPropEnt(iProjectileProp_Send"m_hOwnerEntity");
        if(
iLauncher >= && iLauncher <= MaxClients  && IsClientInGame(iLauncher) &&  IsPlayerAlive(iLauncher))
        {
            
// Check to make sure the projectile isn't already being homed
            
if(GetEntProp(iProjectileProp_Send"m_nForceBone") != 0) return Plugin_Handled;    
            
SetEntProp(iProjectileProp_Send"m_nForceBone"1);
            
            new 
iData[ARRAY_HOMING_SIZE];
            
iData[ArrayHoming_EntityRef] = EntIndexToEntRef(iProjectile);
            
PushArrayArray(g_hArrayHomingiData);
        }
    }
    
    return 
Plugin_Handled;
}

public 
OnGameFrame()
{
    
// Using this method instead of SDKHooks because the Think functions are not called consistently for all projectiles
    
for(new i=GetArraySize(g_hArrayHoming)-1i>=0i--)
    {
        new 
iData[ARRAY_HOMING_SIZE];
        
GetArrayArray(g_hArrayHomingiiData);
        
        if(
iData[ArrayHoming_EntityRef] == 0)
        {
            
RemoveFromArray(g_hArrayHomingi);
            continue;
        }
        
        new 
iProjectile EntRefToEntIndex(iData[ArrayHoming_EntityRef]);
        if(
iProjectile MaxClients)
            
HomingProjectile_Think(iProjectileiData[ArrayHoming_EntityRef], iiData[ArrayHoming_CurrentTarget]);
        else
            
RemoveFromArray(g_hArrayHomingi);
    }
}

public 
HomingProjectile_Think(iProjectileiRefProjectileiArrayIndexiCurrentTarget)
{
    new 
iTeam GetEntProp(iProjectileProp_Send"m_iTeamNum");
    
    if(!
HomingProjectile_IsValidTarget(iCurrentTargetiProjectileiTeam))
        
HomingProjectile_FindTarget(iProjectileiRefProjectileiArrayIndex);
    else
        
HomingProjectile_TurnToTarget(iCurrentTargetiProjectile);
}

bool:HomingProjectile_IsValidTarget(clientiProjectileiTeam)
{
    if(
client >= && client <= MaxClients &&  IsClientInGame(client) && IsPlayerAlive(client) &&  GetClientTeam(client) != iTeam)
    {
        if(
TF2_IsPlayerInCondition(clientTFCond_Cloaked)) return false;
        
        if(
TF2_IsPlayerInCondition(clientTFCond_Disguised) &&  GetEntProp(clientProp_Send"m_nDisguiseTeam") == iTeam)
            return 
false;
        
        new 
Float:flStart[3];
        
GetClientEyePosition(clientflStart);
        new 
Float:flEnd[3];
        
GetEntPropVector(iProjectileProp_Send"m_vecOrigin"flEnd);
        
        new 
Handle:hTrace TR_TraceRayFilterEx(flStartflEndMASK_SOLIDRayType_EndPointTraceFilterHomingiProjectile);
        if(
hTrace != INVALID_HANDLE)
        {
            if(
TR_DidHit(hTrace))
            {
                
CloseHandle(hTrace);
                return 
false;
            }
            
            
CloseHandle(hTrace);
            return 
true;
        }
    }
    
    return 
false;
}

public 
bool:TraceFilterHoming(entitycontentsMaskany:iProjectile)
{
    if(
entity == iProjectile || (entity >= && entity <= MaxClients))
        return 
false;
    
    return 
true;
}

HomingProjectile_FindTarget(iProjectileiRefProjectileiArrayIndex)
{
    new 
iTeam GetEntProp(iProjectileProp_Send"m_iTeamNum");
    new 
Float:flPos1[3];
    
GetEntPropVector(iProjectileProp_Send"m_vecOrigin"flPos1);
    
    new 
iBestTarget;
    new 
Float:flBestLength 99999.9;
    for(new 
i=1i<=MaxClientsi++)
    {
        if(
HomingProjectile_IsValidTarget(iiProjectileiTeam))
        {
            new 
Float:flPos2[3];
            
GetClientEyePosition(iflPos2);
            
            new 
Float:flDistance GetVectorDistance(flPos1flPos2);
            
            
//if(flDistance < 70.0) continue;
            
            
if(flDistance flBestLength)
            {
                
iBestTarget i;
                
flBestLength flDistance;
            }
        }
    }
    
    if(
iBestTarget >= && iBestTarget <= MaxClients)
    {
        new 
iData[ARRAY_HOMING_SIZE];
        
iData[ArrayHoming_EntityRef] = iRefProjectile;
        
iData[ArrayHoming_CurrentTarget] = iBestTarget;
        
SetArrayArray(g_hArrayHomingiArrayIndexiData);
        
        
HomingProjectile_TurnToTarget(iBestTargetiProjectile);
    }
    else
    {
        new 
iData[ARRAY_HOMING_SIZE];
        
iData[ArrayHoming_EntityRef] = iRefProjectile;
        
iData[ArrayHoming_CurrentTarget] = 0;
        
SetArrayArray(g_hArrayHomingiArrayIndexiData);
    }
}
/*
HomingProjectile_TurnToTarget(client, iProjectile)
{
    new Float:flTargetPos[3];
    GetClientAbsOrigin(client, flTargetPos);
    new Float:flRocketPos[3];
    GetEntPropVector(iProjectile, Prop_Send, "m_vecOrigin", flRocketPos);
    new Float:flInitialVelocity[3];
//    GetEntPropVector(iProjectile, Prop_Send, "m_vInitialVelocity", flInitialVelocity);
    GetEntPropVector(iProjectile, Prop_Send, "m_vecAbsVelocity", flInitialVelocity);
    
    new Float:flSpeedInit = GetVectorLength(flInitialVelocity);
    new Float:flSpeedBase = flSpeedInit * GetConVarFloat(g_hCvarHomingSpeed);
    
    flTargetPos[2] += 30 + Pow(GetVectorDistance(flTargetPos, flRocketPos), 2.0) / 10000;
    
    new Float:flNewVec[3];
    SubtractVectors(flTargetPos, flRocketPos, flNewVec);
    NormalizeVector(flNewVec, flNewVec);
    
    new Float:flAng[3];
    GetVectorAngles(flNewVec, flAng);

    new Float:flSpeedNew = flSpeedBase + GetEntProp(iProjectile,  Prop_Send, "m_iDeflected") * flSpeedBase *  GetConVarFloat(g_hCvarHomingReflect);
    
    ScaleVector(flNewVec, flSpeedNew);
    TeleportEntity(iProjectile, NULL_VECTOR, flAng, flNewVec);
}*/

HomingProjectile_TurnToTarget(clientiProjectile)                        // update projectile position
{
    new 
Float:flTargetPos[3];
    
GetClientAbsOrigin(clientflTargetPos);
    new 
Float:flRocketPos[3];
    
GetEntPropVector(iProjectileProp_Send"m_vecOrigin"flRocketPos);
    new 
Float:flRocketVel[3];
    
GetEntPropVector(iProjectileProp_Data"m_vecAbsVelocity"flRocketVel);
        
    
flTargetPos[2] += 30 Pow(GetVectorDistance(flTargetPosflRocketPos), 2.0) / 10000;
        
    new 
Float:flNewVec[3];
    
SubtractVectors(flTargetPosflRocketPosflNewVec);
    
NormalizeVector(flNewVecflNewVec);
        
    new 
Float:flAng[3];
    
GetVectorAngles(flNewVecflAng);

    
ScaleVector(flNewVecgf_RocketSpeed);
    
TeleportEntity(iProjectileNULL_VECTORflAngflNewVec);
}

public 
Action:ProjectileTouchHook(entity,  other)                                // Wat happens when this  projectile touches something
{
    if(
other && other <= MaxClients)
    {
        new 
client GetEntPropEnt(entityProp_Send"m_hOwnerEntity");
        if(
client && client <= MaxClients &&  IsClientInGame(client))        // will probably just be -1, but  whatever.
        
{
            
SDKHooks_TakeDamage(otherclientclientgf_RocketDamageDMG_SHOCK|DMG_ALWAYSGIB);
        }
    }
}

stock AttachParticle(iEntity, const String:strParticleEffect[], const  String:strAttachPoint[]=""Float:flZOffset=0.0,  Float:flSelfDestruct=0.0

    if (
MapStarted)
    {
        new 
iParticle CreateEntityByName("info_particle_system"); 
        if( !
IsValidEdict(iParticle) ) 
            return 
0
         
        new 
Float:flPos[3]; 
        
GetEntPropVector(iEntityProp_Send"m_vecOrigin"flPos); 
        
flPos[2] += flZOffset
         
        
TeleportEntity(iParticleflPosNULL_VECTORNULL_VECTOR); 
         
        
DispatchKeyValue(iParticle"effect_name"strParticleEffect); 
        
DispatchSpawn(iParticle); 
         
        
SetVariantString("!activator"); 
        
AcceptEntityInput(iParticle"SetParent"iEntity); 
        
ActivateEntity(iParticle); 
         
        if(
strlen(strAttachPoint)) 
        { 
            
SetVariantString(strAttachPoint); 
            
AcceptEntityInput(iParticle"SetParentAttachmentMaintainOffset"); 
        } 
         
        
AcceptEntityInput(iParticle"start"); 
         
        if( 
flSelfDestruct 0.0 
            
CreateTimerflSelfDestructTimer_DeleteParticleEntIndexToEntRef(iParticle) ); 
         
        return 
iParticle
    }
    return 
0;
}

public 
Action:Timer_DeleteParticle(Handle:hTimerany:iRefEnt

    new 
iEntity EntRefToEntIndex(iRefEnt); 
    if(
iEntity MaxClients
        
AcceptEntityInput(iEntity"Kill"); 
     
    return 
Plugin_Handled
}

public 
bool:TraceRayDontHitSelf(entitymaskany:data)
{
    return 
entity != data;
}

public 
bool:TraceRayFilterClients(entitymaskany:data)
{
    if(
entity && entity <=MaxClients)                    // only hit the client we're aiming at
    
{
        if(
entity == data)
            return 
true;
        else
            return 
false;
    }
    return 
true;
}

bool:CanSeeTarget(Float:startpos[3], Float:targetpos[3], target,  bossteam)        // Tests to see if vec1 > vec2 can "see" target
{
    
TR_TraceRayFilter(startpostargetposMASK_SOLIDRayType_EndPointTraceRayFilterClientstarget);

    if(
TR_GetEntityIndex() == target)
    {
        if(
TF2_GetPlayerClass(target) ==  TFClass_Spy)                            // if they are a spy, do extra  tests (coolrocket stuff?)
        
{
            if(
TF2_IsPlayerInCondition(targetTFCond_Cloaked))                    // if they are cloaked
            
{
                if(
TF2_IsPlayerInCondition(targetTFCond_CloakFlicker)            // check if they are partially visible
                    
|| TF2_IsPlayerInCondition(targetTFCond_OnFire)
                    || 
TF2_IsPlayerInCondition(targetTFCond_Jarated)
                    || 
TF2_IsPlayerInCondition(targetTFCond_Milked)
                    || 
TF2_IsPlayerInCondition(targetTFCond_Bleeding))
                {
                    return 
true;
                }
                return 
false;
            }
            return 
true;
        }
        if(
GetClientTeam(target) == bossteam)
        {
            return 
false;
        }
        return 
true;
    }
    return 
false;
}

stock bool:IsValidClient(client)
{
    if(
client <= ) return false;
    if(
client MaxClients) return false;
    if(!
IsClientConnected(client)) return false;
    return 
IsClientInGame(client);


Last edited by DJPlaya; 07-26-2015 at 09:02.
DJPlaya is offline
Send a message via Skype™ to DJPlaya