Veteran Member
Join Date: Sep 2012
Location: Just behind my PC screen
|
02-10-2015
, 12:59
Re: dispenser shooting homing rockets did that ever come out publicly?
|
#5
|
Here is the source code (compille it). Again, I did nothing but posting this here. All credits goes to him.
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.5, timer_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(index, Prop_Send, "m_hBuilder"); new iAmmo = GetEntProp(index, Prop_Send, "m_iAmmoMetal"); new newiAmmo = iAmmo -= 40; if(IsValidClient(client)) { new bossteam = GetClientTeam(client); decl playerarray[MAXPLAYERS+1]; new playercount; new bool:disBuilding = GetEntProp(index, Prop_Send, "m_bBuilding") == 1; new bool:disPlacing = GetEntProp(index, Prop_Send, "m_bPlacing") == 1; new bool:disCarried = GetEntProp(index, Prop_Send, "m_bCarried") == 1; GetEntPropVector(index, Prop_Send, "m_vecOrigin", dPos); //GetEntPropVector(index, Prop_Send, "m_angRotation", dAng);
if(!disBuilding && !disPlacing && !disCarried) { new disLevel = GetEntProp(index, Prop_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(dPos, dAng, MASK_SOLID, RayType_Infinite, TraceRayDontHitSelf, client); TR_GetEndPosition(targetvector);
for(new player = 1; player <= MaxClients; player++) { if(player != client && IsClientInGame(player) && IsPlayerAlive(player)) { if(HomingProjectile_IsValidTarget(player, index, GetEntProp(index, Prop_Send, "m_iTeamNum"))) { GetClientEyePosition(player, playerpos); playerpos[2] -= 30.0; if(GetVectorDistance(dPos, playerpos, true) < gf_RocketDistance && CanSeeTarget(dPos, playerpos, player, bossteam)) { 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.0, 8.0); EmitAmbientSound(SND_SHOOT, dPos, index); SetEntProp(index, Prop_Send, "m_iAmmoMetal", newiAmmo); //It costs 40 metal to shoot a rocket CreateProjectile(client, dPos); //Fire a rocket } } } } } } }
CreateProjectile(client, Float:origin[3]) { new entity = CreateEntityByName("tf_projectile_rocket"); if(entity != -1) { DispatchSpawn(entity); SetEntProp(entity, Prop_Send, "m_CollisionGroup", 4); SetEntProp(entity, Prop_Send, "m_iTeamNum", GetClientTeam(client)); SetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity", client); SetEntPropVector(entity, Prop_Send, "m_vecMins", Float:{0.0,0.0,0.0}); SetEntPropVector(entity, Prop_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(vAngles, vBuffer, NULL_VECTOR, NULL_VECTOR); vVelocity[0] = vBuffer[0]*gf_RocketSpeed; vVelocity[1] = vBuffer[1]*gf_RocketSpeed; vVelocity[2] = vBuffer[2]*gf_RocketSpeed; SetEntityModel(entity, MDL_ROCKET); SetEntProp(entity, Prop_Send, "m_bCritical", true); TeleportEntity(entity, origin, vAngles, vVelocity); SDKHook(entity, SDKHook_StartTouch, ProjectileTouchHook); CreateTimer(0.35, Timer_CheckOwnership, EntIndexToEntRef(entity)); } }
public Action:Timer_CheckOwnership(Handle:hTimer, any:iRef) { new iProjectile = EntRefToEntIndex(iRef); if(iProjectile > MaxClients && IsValidEntity(iProjectile)) { new iLauncher = GetEntPropEnt(iProjectile, Prop_Send, "m_hOwnerEntity"); if(iLauncher >= 1 && iLauncher <= MaxClients && IsClientInGame(iLauncher) && IsPlayerAlive(iLauncher)) { // Check to make sure the projectile isn't already being homed if(GetEntProp(iProjectile, Prop_Send, "m_nForceBone") != 0) return Plugin_Handled; SetEntProp(iProjectile, Prop_Send, "m_nForceBone", 1); new iData[ARRAY_HOMING_SIZE]; iData[ArrayHoming_EntityRef] = EntIndexToEntRef(iProjectile); PushArrayArray(g_hArrayHoming, iData); } } 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)-1; i>=0; i--) { new iData[ARRAY_HOMING_SIZE]; GetArrayArray(g_hArrayHoming, i, iData); if(iData[ArrayHoming_EntityRef] == 0) { RemoveFromArray(g_hArrayHoming, i); continue; } new iProjectile = EntRefToEntIndex(iData[ArrayHoming_EntityRef]); if(iProjectile > MaxClients) HomingProjectile_Think(iProjectile, iData[ArrayHoming_EntityRef], i, iData[ArrayHoming_CurrentTarget]); else RemoveFromArray(g_hArrayHoming, i); } }
public HomingProjectile_Think(iProjectile, iRefProjectile, iArrayIndex, iCurrentTarget) { new iTeam = GetEntProp(iProjectile, Prop_Send, "m_iTeamNum"); if(!HomingProjectile_IsValidTarget(iCurrentTarget, iProjectile, iTeam)) HomingProjectile_FindTarget(iProjectile, iRefProjectile, iArrayIndex); else HomingProjectile_TurnToTarget(iCurrentTarget, iProjectile); }
bool:HomingProjectile_IsValidTarget(client, iProjectile, iTeam) { if(client >= 1 && client <= MaxClients && IsClientInGame(client) && IsPlayerAlive(client) && GetClientTeam(client) != iTeam) { if(TF2_IsPlayerInCondition(client, TFCond_Cloaked)) return false; if(TF2_IsPlayerInCondition(client, TFCond_Disguised) && GetEntProp(client, Prop_Send, "m_nDisguiseTeam") == iTeam) return false; new Float:flStart[3]; GetClientEyePosition(client, flStart); new Float:flEnd[3]; GetEntPropVector(iProjectile, Prop_Send, "m_vecOrigin", flEnd); new Handle:hTrace = TR_TraceRayFilterEx(flStart, flEnd, MASK_SOLID, RayType_EndPoint, TraceFilterHoming, iProjectile); if(hTrace != INVALID_HANDLE) { if(TR_DidHit(hTrace)) { CloseHandle(hTrace); return false; } CloseHandle(hTrace); return true; } } return false; }
public bool:TraceFilterHoming(entity, contentsMask, any:iProjectile) { if(entity == iProjectile || (entity >= 1 && entity <= MaxClients)) return false; return true; }
HomingProjectile_FindTarget(iProjectile, iRefProjectile, iArrayIndex) { new iTeam = GetEntProp(iProjectile, Prop_Send, "m_iTeamNum"); new Float:flPos1[3]; GetEntPropVector(iProjectile, Prop_Send, "m_vecOrigin", flPos1); new iBestTarget; new Float:flBestLength = 99999.9; for(new i=1; i<=MaxClients; i++) { if(HomingProjectile_IsValidTarget(i, iProjectile, iTeam)) { new Float:flPos2[3]; GetClientEyePosition(i, flPos2); new Float:flDistance = GetVectorDistance(flPos1, flPos2); //if(flDistance < 70.0) continue; if(flDistance < flBestLength) { iBestTarget = i; flBestLength = flDistance; } } } if(iBestTarget >= 1 && iBestTarget <= MaxClients) { new iData[ARRAY_HOMING_SIZE]; iData[ArrayHoming_EntityRef] = iRefProjectile; iData[ArrayHoming_CurrentTarget] = iBestTarget; SetArrayArray(g_hArrayHoming, iArrayIndex, iData); HomingProjectile_TurnToTarget(iBestTarget, iProjectile); } else { new iData[ARRAY_HOMING_SIZE]; iData[ArrayHoming_EntityRef] = iRefProjectile; iData[ArrayHoming_CurrentTarget] = 0; SetArrayArray(g_hArrayHoming, iArrayIndex, iData); } } /* 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(client, iProjectile) // update projectile position { new Float:flTargetPos[3]; GetClientAbsOrigin(client, flTargetPos); new Float:flRocketPos[3]; GetEntPropVector(iProjectile, Prop_Send, "m_vecOrigin", flRocketPos); new Float:flRocketVel[3]; GetEntPropVector(iProjectile, Prop_Data, "m_vecAbsVelocity", flRocketVel); 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);
ScaleVector(flNewVec, gf_RocketSpeed); TeleportEntity(iProjectile, NULL_VECTOR, flAng, flNewVec); }
public Action:ProjectileTouchHook(entity, other) // Wat happens when this projectile touches something { if(other > 0 && other <= MaxClients) { new client = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity"); if(client > 0 && client <= MaxClients && IsClientInGame(client)) // will probably just be -1, but whatever. { SDKHooks_TakeDamage(other, client, client, gf_RocketDamage, DMG_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(iEntity, Prop_Send, "m_vecOrigin", flPos); flPos[2] += flZOffset; TeleportEntity(iParticle, flPos, NULL_VECTOR, NULL_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 ) CreateTimer( flSelfDestruct, Timer_DeleteParticle, EntIndexToEntRef(iParticle) ); return iParticle; } return 0; }
public Action:Timer_DeleteParticle(Handle:hTimer, any:iRefEnt) { new iEntity = EntRefToEntIndex(iRefEnt); if(iEntity > MaxClients) AcceptEntityInput(iEntity, "Kill"); return Plugin_Handled; }
public bool:TraceRayDontHitSelf(entity, mask, any:data) { return entity != data; }
public bool:TraceRayFilterClients(entity, mask, any:data) { if(entity > 0 && 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(startpos, targetpos, MASK_SOLID, RayType_EndPoint, TraceRayFilterClients, target);
if(TR_GetEntityIndex() == target) { if(TF2_GetPlayerClass(target) == TFClass_Spy) // if they are a spy, do extra tests (coolrocket stuff?) { if(TF2_IsPlayerInCondition(target, TFCond_Cloaked)) // if they are cloaked { if(TF2_IsPlayerInCondition(target, TFCond_CloakFlicker) // check if they are partially visible || TF2_IsPlayerInCondition(target, TFCond_OnFire) || TF2_IsPlayerInCondition(target, TFCond_Jarated) || TF2_IsPlayerInCondition(target, TFCond_Milked) || TF2_IsPlayerInCondition(target, TFCond_Bleeding)) { return true; } return false; } return true; } if(GetClientTeam(target) == bossteam) { return false; } return true; } return false; }
stock bool:IsValidClient(client) { if(client <= 0 ) return false; if(client > MaxClients) return false; if(!IsClientConnected(client)) return false; return IsClientInGame(client); }
__________________
Last edited by Arkarr; 02-10-2015 at 13:02.
|
|