FlacoBey

Untitled

Jan 10th, 2019
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.13 KB | None | 0 0
  1. #pragma semicolon 1
  2.  
  3. #include <sourcemod>
  4. #include <sdktools>
  5. #include <sdkhooks>
  6.  
  7. #define REQUIRE_PLUGIN
  8. #include <LMCL4D2CDeathHandler>
  9. #include <LMCCore>
  10.  
  11. #pragma newdecls required
  12.  
  13. #define PLUGIN_VERSION "1.0"
  14.  
  15. #define RAGDOLL_OFFSET_TOLERANCE 25.0
  16.  
  17. static int iDeathModelRef[2048+1];
  18. static int iRagdollRef[2048+1];
  19. static float fRagdollVelocity[2048+1][3];
  20. static int iRagdollPushesLeft[2048+1];
  21. static float fClientVelocity[MAXPLAYERS+1][3];
  22. static bool bIncap[MAXPLAYERS+1];
  23.  
  24. static bool bSpawnedGlowModels = false;
  25. static bool bShowGlow[MAXPLAYERS+1];
  26. static int iGlowModelRef[2048+1];
  27.  
  28. static const char sFatOrBugModels[12][] =
  29. {
  30.     "models/survivors/survivor_gambler.mdl",
  31.     "models/survivors/survivor_producer.mdl",
  32.     "models/survivors/survivor_coach.mdl",
  33.     "models/survivors/survivor_mechanic.mdl",
  34.     "models/survivors/survivor_namvet.mdl",
  35.     "models/survivors/survivor_teenangst.mdl",
  36.     "models/survivors/survivor_teenangst_light.mdl",
  37.     "models/survivors/survivor_biker.mdl",
  38.     "models/survivors/survivor_biker_light.mdl",
  39.     "models/survivors/survivor_manager.mdl",
  40.     "models/npcs/rescue_pilot_01.mdl",
  41.     "models/infected/common_female01.mdl"
  42. };
  43.  
  44. static const char sPlaceHolder[] = "models/infected/common_male01.mdl";
  45.  
  46.  
  47. public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
  48. {
  49.     if(GetEngineVersion() != Engine_Left4Dead2 )
  50.     {
  51.         strcopy(error, err_max, "Plugin only supports Left 4 Dead 2");
  52.         return APLRes_SilentFailure;
  53.     }
  54.     return APLRes_Success;
  55. }
  56.  
  57. public void OnPluginStart()
  58. {
  59.     CreateConVar("defib_Ragdolls_version", PLUGIN_VERSION, "", FCVAR_NOTIFY|FCVAR_DONTRECORD);
  60.     CreateTimer(0.1, GlowThink, _, TIMER_REPEAT);
  61. }
  62.  
  63. public void OnMapStart()
  64. {
  65.     PrecacheModel(sPlaceHolder, true);
  66. }
  67.  
  68. public void LMC_OnClientDeathModelCreated(int iClient, int iDeathModel, int iOverlayModel)
  69. {
  70.     int iEntity = CreateEntityByName("physics_prop_ragdoll");
  71.     if(iEntity < 1)
  72.         return;
  73.    
  74.     char sModel[PLATFORM_MAX_PATH];
  75.    
  76.     if(iOverlayModel > -1)
  77.     {
  78.         GetEntPropString(iOverlayModel, Prop_Data, "m_ModelName", sModel, sizeof(sModel));
  79.         AcceptEntityInput(iOverlayModel, "Kill");
  80.     }
  81.     else
  82.         GetEntPropString(iClient, Prop_Data, "m_ModelName", sModel, sizeof(sModel));
  83.    
  84.     if(sModel[0] == '\0')
  85.     {
  86.         AcceptEntityInput(iEntity, "Kill");
  87.         return;
  88.     }
  89.    
  90.     if(IsFatOrBugModel(sModel))
  91.     {
  92.         int iOverlay = LMC_SetEntityOverlayModel(iEntity, sModel);
  93.         if(iOverlay < 1)
  94.         {
  95.             AcceptEntityInput(iEntity, "Kill");
  96.             return;
  97.         }
  98.         DispatchKeyValue(iEntity, "model", sPlaceHolder);
  99.         SetEntProp(iEntity, Prop_Send, "m_nMinGPULevel", 1);
  100.         SetEntProp(iEntity, Prop_Send, "m_nMaxGPULevel", 1);
  101.         SetEntityRenderMode(iEntity, RENDER_NONE);
  102.     }
  103.     else
  104.         DispatchKeyValue(iEntity, "model", sModel);
  105.    
  106.    
  107.     DispatchKeyValue(iEntity, "spawnflags", "4");
  108.    
  109.     float fVec[3];
  110.     GetEntPropVector(iDeathModel, Prop_Send, "m_vecOrigin", fVec);
  111.     if(!bIncap[iClient])
  112.         fVec[2] += 10.0;// so legs dont get stuck in the floor
  113.    
  114.     TeleportEntity(iEntity, fVec, NULL_VECTOR, NULL_VECTOR);
  115.     TeleportEntity(iDeathModel, fVec, NULL_VECTOR, NULL_VECTOR);
  116.    
  117.     DispatchSpawn(iEntity);
  118.     ActivateEntity(iEntity);
  119.    
  120.     AcceptEntityInput(iEntity, "TurnOn");
  121.    
  122.     GetEntPropVector(iDeathModel, Prop_Data, "m_angAbsRotation", fVec);
  123.     FixAngles(sModel, fVec[0], bIncap[iClient]);
  124.     TeleportEntity(iEntity, NULL_VECTOR, fVec, NULL_VECTOR);
  125.    
  126.     SetEdictFlags(iDeathModel, FL_EDICT_DONTSEND);
  127.    
  128.     iDeathModelRef[iDeathModel] = EntIndexToEntRef(iEntity);
  129.     iRagdollRef[iEntity] = EntIndexToEntRef(iDeathModel);
  130.    
  131.     if(bSpawnedGlowModels)
  132.         SetUpGlowModel(iEntity);
  133.    
  134.     CreateTimer(1.0, CheckDist, iRagdollRef[iEntity], TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);// for plugins or maps that like to teleport deathmodels around parenting wont work for this (e.g tank_challenge)
  135.     SDKHook(iEntity, SDKHook_VPhysicsUpdatePost, RagdollPhysicsUpdatePost);
  136.     SDKHook(iEntity, SDKHook_VPhysicsUpdate, VPhysicsPush);
  137.     SDKHook(iEntity, SDKHook_OnTakeDamage, ApplyRagdollForce);
  138.    
  139.     int iTickRate = RoundFloat(1 / GetTickInterval());
  140.     fRagdollVelocity[iEntity][0] = fClientVelocity[iClient][0] / (iTickRate / 30);
  141.     fRagdollVelocity[iEntity][1] = fClientVelocity[iClient][1] / (iTickRate / 30);
  142.     fRagdollVelocity[iEntity][2] = fClientVelocity[iClient][2] / (iTickRate / 30);
  143.    
  144.     ScaleVector(fRagdollVelocity[iEntity], 5.0);
  145.     iRagdollPushesLeft[iEntity] = iTickRate;
  146. }
  147.  
  148.  
  149. public void VPhysicsPush(int iEntity)
  150. {
  151.     if(iRagdollPushesLeft[iEntity] < 1)
  152.     {
  153.         SDKUnhook(iEntity, SDKHook_OnTakeDamage, ApplyRagdollForce);
  154.         SDKUnhook(iEntity, SDKHook_VPhysicsUpdate, VPhysicsPush);
  155.         SetEntityRenderMode(iEntity, RENDER_NORMAL);
  156.         return;
  157.     }
  158.    
  159.     --iRagdollPushesLeft[iEntity];
  160.     TickleRagdoll(iEntity);
  161. }
  162.  
  163. public Action ApplyRagdollForce(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3])
  164. {
  165.     damageForce[0] = fRagdollVelocity[victim][0];
  166.     damageForce[1] = fRagdollVelocity[victim][1];
  167.     damageForce[2] = fRagdollVelocity[victim][2];
  168.     GetEntPropVector(victim, Prop_Send, "m_vecOrigin", damagePosition);
  169.     AddVectors(fRagdollVelocity[victim], damagePosition, damagePosition);
  170.     return Plugin_Changed;
  171. }
  172.  
  173. bool IsFatOrBugModel(const char[] sModel)
  174. {
  175.     for(int i = 0; i < 12; i++)
  176.     {
  177.         if(StrEqual(sModel, sFatOrBugModels[i], false))
  178.             return true;
  179.     }
  180.     return false;
  181. }
  182.  
  183. public Action ShouldTransmitGlow(int iEntity, int iClient)
  184. {
  185.     if(bShowGlow[iClient])
  186.         return Plugin_Continue;
  187.     return Plugin_Handled;
  188. }
  189.  
  190. public Action CheckDist(Handle hTimer, int iEntRef)
  191. {
  192.     if(!IsValidEntRef(iEntRef))
  193.         return Plugin_Stop;
  194.    
  195.     static int iEntity;
  196.     iEntity = EntRefToEntIndex(iEntRef);
  197.     if(!IsValidEntRef(iDeathModelRef[iEntity]))
  198.         return Plugin_Stop;
  199.  
  200.     CheckDeathModelTeleport(iDeathModelRef[iEntity], iEntity);
  201.     return Plugin_Continue;
  202. }
  203.  
  204. public void RagdollPhysicsUpdatePost(int iEntity)
  205. {
  206.     if(!IsValidEntRef(iRagdollRef[iEntity]))
  207.         return;
  208.    
  209.     CheckDeathModelTeleport(iEntity, iRagdollRef[iEntity]);
  210. }
  211.  
  212. void CheckDeathModelTeleport(int iRagdoll, int iDeathModel)
  213. {
  214.     static float fPos1[3];
  215.     static float fPos2[3];
  216.     GetEntPropVector(iRagdoll, Prop_Send, "m_vecOrigin", fPos1);
  217.     GetEntPropVector(iDeathModel, Prop_Send, "m_vecOrigin", fPos2);
  218.    
  219.     if(GetVectorDistance(fPos1, fPos2) > RAGDOLL_OFFSET_TOLERANCE)
  220.     {
  221.         fPos2[2] += 35.0;
  222.         TeleportEntity(iRagdoll, fPos2, NULL_VECTOR, NULL_VECTOR);
  223.         TeleportEntity(iDeathModel, fPos2, NULL_VECTOR, NULL_VECTOR);
  224.         TickleRagdoll(iRagdoll);//incase the ragdoll is sleeping triggers vphysics
  225.     }
  226.     else
  227.         TeleportEntity(iDeathModel, fPos1, NULL_VECTOR, NULL_VECTOR);
  228. }
  229.  
  230. public void OnEntityDestroyed(int iEntity)
  231. {
  232.     if(iEntity < 1 || iEntity > 2048)
  233.         return;
  234.    
  235.     if(IsValidEntRef(iDeathModelRef[iEntity]))
  236.     {
  237.         AcceptEntityInput(iDeathModelRef[iEntity], "kill");
  238.         iDeathModelRef[iEntity] = -1;
  239.     }
  240.     if(IsValidEntRef(iRagdollRef[iEntity]))
  241.     {
  242.         AcceptEntityInput(iRagdollRef[iEntity], "kill");
  243.         iRagdollRef[iEntity] = -1;
  244.     }
  245. }
  246.  
  247. public void OnClientPutInServer(int iClient)
  248. {
  249.     if(IsFakeClient(iClient))
  250.         return;
  251.    
  252.     SDKHook(iClient, SDKHook_OnTakeDamageAlivePost, eOnTakeDamagePost);
  253. }
  254.  
  255. public void eOnTakeDamagePost(int victim, int attacker, int inflictor, float damage, int damagetype, int weapon, const float damageForce[3], const float damagePosition[3])
  256. {
  257.     if(GetEntProp(victim, Prop_Send, "m_isIncapacitated", 1) && !GetEntProp(victim, Prop_Send, "m_isHangingFromLedge", 1))
  258.         bIncap[victim] = true;
  259.     else
  260.         bIncap[victim] = false;
  261.        
  262.     fClientVelocity[victim][0] = damageForce[0];
  263.     fClientVelocity[victim][1] = damageForce[1];
  264.     fClientVelocity[victim][2] = damageForce[2];
  265. }
  266.  
  267. void FixAngles(const char[] sModel, float &fAng, bool IncapAngle)
  268. {
  269.     if(IncapAngle)
  270.     {
  271.         if(StrEqual(sModel, "models/infected/witch_bride.mdl", false))
  272.             fAng = -180.0;
  273.         else
  274.             fAng = -90.0;
  275.     }
  276.     else if(StrEqual(sModel, "models/infected/witch_bride.mdl", false))
  277.         fAng = -90.0;
  278. }
  279.  
  280. static bool IsValidEntRef(int iEntRef)
  281. {
  282.     return (iEntRef != 0 && EntRefToEntIndex(iEntRef) != INVALID_ENT_REFERENCE);
  283. }
  284.  
  285. //credit smlib as guide for pointhurt
  286. static void TickleRagdoll(int iRagdoll)
  287. {
  288.     static int iHurtPointRef = INVALID_ENT_REFERENCE;
  289.     if(!IsValidEntRef(iHurtPointRef))
  290.     {
  291.         iHurtPointRef = EntIndexToEntRef(CreateEntityByName("point_hurt"));
  292.         if (iHurtPointRef == INVALID_ENT_REFERENCE)
  293.             return;
  294.        
  295.         DispatchSpawn(iHurtPointRef);
  296.     }
  297.    
  298.     char sTarget[32];
  299.     FormatEx(sTarget, sizeof(sTarget), "__TickleTarget%i", iRagdoll);
  300.     DispatchKeyValue(iHurtPointRef, "DamageTarget", sTarget);
  301.     DispatchKeyValue(iRagdoll, "targetname", sTarget);
  302.     SetEntProp(iHurtPointRef, Prop_Data, "m_bitsDamageType", DMG_CLUB);
  303.     AcceptEntityInput(iHurtPointRef, "TurnOn");
  304.     AcceptEntityInput(iHurtPointRef, "Hurt");
  305.     AcceptEntityInput(iHurtPointRef, "TurnOff");
  306. }
  307.  
  308. public Action GlowThink(Handle hTimer, any Cake)
  309. {
  310.     static int i;
  311.     static bool bHasDefib;
  312.     bHasDefib = false;
  313.     for(i = 1; i <= MaxClients; i++)
  314.     {
  315.         if(!IsClientInGame(i) || IsFakeClient(i) || GetClientTeam(i) != 2)
  316.             continue;
  317.        
  318.         static char sWeapon[32];
  319.         GetClientWeapon(i, sWeapon, sizeof(sWeapon));
  320.         if(sWeapon[7] == 'd' && StrEqual(sWeapon, "weapon_defibrillator", false))
  321.         {
  322.             bHasDefib = true;
  323.             bShowGlow[i] = true;
  324.             continue;
  325.         }
  326.     }
  327.  
  328.     if(bSpawnedGlowModels && !bHasDefib)
  329.     {
  330.         for(i = MaxClients; i <= 2048; i++)
  331.             if(IsValidEntRef(iGlowModelRef[i]))
  332.                 AcceptEntityInput(iGlowModelRef[i], "Kill");
  333.         bSpawnedGlowModels = false;
  334.        
  335.         for(i = 1; i <= MaxClients; i++)
  336.             bShowGlow[i] = false;
  337.     }
  338.     else if(!bSpawnedGlowModels && bHasDefib)
  339.     {
  340.         for(i = MaxClients; i <= 2048; i++)
  341.             if(IsValidEntRef(iDeathModelRef[i]))
  342.                 if(!SetUpGlowModel(EntRefToEntIndex(iDeathModelRef[i])))
  343.                     break;
  344.                
  345.         bSpawnedGlowModels = true;
  346.     }
  347. }
  348.  
  349.  
  350. bool SetUpGlowModel(int iEntity)
  351. {
  352.     static int iEnt;
  353.     iEnt = CreateEntityByName("prop_dynamic_ornament");
  354.     if(iEnt < 0)
  355.         return false;
  356.    
  357.     static char sModel[PLATFORM_MAX_PATH];
  358.     static int iOverlayModel;
  359.     iOverlayModel = LMC_GetEntityOverlayModel(iEntity);
  360.     if(iOverlayModel > -1)
  361.         GetEntPropString(iOverlayModel, Prop_Data, "m_ModelName", sModel, sizeof(sModel));
  362.     else
  363.         GetEntPropString(iEntity, Prop_Data, "m_ModelName", sModel, sizeof(sModel));
  364.    
  365.     DispatchKeyValue(iEnt, "model", sModel);
  366.    
  367.     DispatchSpawn(iEnt);
  368.     ActivateEntity(iEnt);
  369.    
  370.     SetVariantString("!activator");
  371.     AcceptEntityInput(iEnt, "SetParent", iEntity);
  372.    
  373.     SetVariantString("!activator");
  374.     AcceptEntityInput(iEnt, "SetAttached", iEntity);
  375.     AcceptEntityInput(iEnt, "TurnOn");
  376.    
  377.     iGlowModelRef[iEnt] = EntIndexToEntRef(iEnt);
  378.    
  379.     SetEntProp(iEnt, Prop_Send, "m_iGlowType", 3);
  380.     SetEntProp(iEnt, Prop_Send, "m_glowColorOverride", 180);
  381.     SetEntProp(iEnt, Prop_Send, "m_nGlowRange", 2147483646);
  382.     SetEntProp(iEnt, Prop_Send, "m_nMinGPULevel", 1);
  383.     SetEntProp(iEnt, Prop_Send, "m_nMaxGPULevel", 1);
  384.     SetEntityRenderMode(iEnt, RENDER_NONE);
  385.     SDKHook(iEnt, SDKHook_SetTransmit, ShouldTransmitGlow);
  386.     return true;
  387. }
  388.  
  389. public void OnEntityCreated(int iEntity, const char[] sClassname)
  390. {
  391.     if(sClassname[0] != 's' || !StrEqual(sClassname, "survivor_bot"))
  392.         return;
  393.      
  394.     SDKHook(iEntity, SDKHook_OnTakeDamageAlivePost, eOnTakeDamagePost);
  395. }
Advertisement
Add Comment
Please, Sign In to add comment