From 63bfb9e65320d25b36ece301b18c7290218e6789 Mon Sep 17 00:00:00 2001 From: BeeepG <154726445+BeeepG@users.noreply.github.com> Date: Sun, 8 Feb 2026 06:55:06 +0900 Subject: [PATCH 01/24] New vic enemies for construction (#1220) * a * changes * changessss * fix * adds * killme * fixes * aaaa * Update npc_boltbag.sp * aaaaa * aaa * Update npc_giant_armored_medic.sp * aaaa * aaa * aaa * Update zombieriot.phrases.status_effects.txt --- .../configs/zombie_riot/dungeon/raid_3_4.cfg | 444 ++++++++++ .../scripting/shared/status_effects.sp | 14 + addons/sourcemod/scripting/zombie_riot/npc.sp | 24 + .../construction2/victorians/npc_airraider.sp | 545 +++++++++++++ .../construction2/victorians/npc_boltbag.sp | 297 +++++++ .../victorians/npc_chemical_specialist.sp | 351 ++++++++ .../victorians/npc_chemical_spreader.sp | 341 ++++++++ .../victorians/npc_demolitionist.sp | 330 ++++++++ .../construction2/victorians/npc_gasleader.sp | 770 ++++++++++++++++++ .../victorians/npc_giant_armored_medic.sp | 375 +++++++++ .../victorians/npc_headhunter.sp | 449 ++++++++++ .../construction2/victorians/npc_protector.sp | 374 +++++++++ .../construction2/victorians/npc_zapmarker.sp | 395 +++++++++ .../zombieriot.phrases.item.gift.desc.txt | 37 +- .../zombieriot.phrases.status_effects.txt | 10 + .../zombieriot.phrases.zombienames.txt | 36 + 16 files changed, 4791 insertions(+), 1 deletion(-) create mode 100644 addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_airraider.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_boltbag.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_specialist.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_spreader.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_demolitionist.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_gasleader.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_giant_armored_medic.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_headhunter.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_protector.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_zapmarker.sp diff --git a/addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg b/addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg new file mode 100644 index 0000000000..b8777687e0 --- /dev/null +++ b/addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg @@ -0,0 +1,444 @@ +"Waves" +{ + "1" + { + + } + "2" + { + "music_1" + { + "file" "#zombiesurvival/dungeon/raid_attack_3.mp3" + "time" "72" + "volume" "1.4" + "download" "1" + "name" "Stealth Blades" + "author" "Galaxy On Fire 2" + } + "1.5" + { + "count" "3" + "health" "30000" + "extra_damage" "3.0" + "plugin" "npc_blocker" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "25000" + "extra_damage" "3.0" + "plugin" "npc_resource_collector" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "15000" + "extra_damage" "1.0" + "plugin" "npc_chaos_gunmen" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "4" + "health" "50000" + "extra_damage" "2.0" + "plugin" "npc_contracted_motivator" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "50000" + "extra_damage" "2.0" + "extra_speed" "1.0" + "plugin" "npc_mechafist" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "30000" + "extra_damage" "1.0" + "plugin" "npc_headhunter" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "50000" + "extra_damage" "1.35" + "plugin" "npc_ambusher" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "55000" + "extra_damage" "1.0" + "plugin" "npc_mortar" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "250000" + "extra_damage" "1.75" + "extra_thinkspeed" "0.5" + "data" "only" + "plugin" "npc_avangard" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "45000" + "extra_damage" "1.0" + "plugin" "npc_chemical_specialist" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "40000" + "extra_damage" "1.25" + "plugin" "npc_zapmarker" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "25000" + "extra_damage" "1.35" + "plugin" "npc_hardener" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "30000" + "extra_damage" "2.0" + "plugin" "npc_agent_61" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "55000" + "extra_damage" "1.5" + "plugin" "npc_mortar" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "15000" + "extra_damage" "1.0" + "plugin" "npc_chaos_gunmen" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "60000" + "extra_damage" "2.0" + "plugin" "npc_catapult" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "35000" + "extra_damage" "1.0" + "plugin" "npc_airraider" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "4" + "health" "50000" + "extra_damage" "2.0" + "plugin" "npc_contracted_motivator" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "30000" + "extra_damage" "1.0" + "plugin" "npc_protector" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "70000" + "extra_damage" "1.5" + "extra_speed" "0.75" + "plugin" "npc_zombie_engineer_grave" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "8" + "health" "50000" + "extra_damage" "3.0" + "plugin" "npc_barbaric_teardown" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "75000" + "extra_damage" "1.35" + "plugin" "npc_giant_armored_medic" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "35000" + "extra_damage" "1.25" + "plugin" "npc_taser" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "40000" + "extra_damage" "2.5" + "plugin" "npc_victorian_artillerist" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "200000" + "extra_damage" "2.00" + "plugin" "npc_ironshield" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "0" + "health" "2000000" + "is_boss" "1" + "extra_damage" "1.25" + "plugin" "npc_gasleader" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "0" + "health" "90000" + "extra_damage" "1.75" + "plugin" "npc_signaller" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "4" + "health" "35000" + "extra_damage" "1.0" + "plugin" "npc_airraider" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "30000" + "extra_damage" "1.0" + "plugin" "npc_headhunter" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "150000" + "extra_damage" "1.35" + "plugin" "npc_demon_possesed_armor" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "25000" + "extra_damage" "2.00" + "plugin" "npc_hardener" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "275000" + "extra_damage" "1.5" + "plugin" "npc_demolitionist" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "35000" + "extra_damage" "1.25" + "plugin" "npc_protector" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "8" + "health" "50000" + "extra_damage" "3.0" + "plugin" "npc_barbaric_teardown" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "15000" + "extra_damage" "1.0" + "plugin" "npc_chaos_gunmen" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "25000" + "extra_damage" "1.25" + "plugin" "npc_resource_collector" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "32500" + "extra_damage" "2.2" + "plugin" "npc_victorian_artillerist" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "1" + "health" "75000" + "extra_damage" "1.25" + "plugin" "npc_victorian_tank" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "45000" + "extra_damage" "1.35" + "plugin" "npc_chemical_specialist" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "40000" + "extra_damage" "1.35" + "plugin" "npc_zapmarker" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "60000" + "extra_damage" "2.0" + "plugin" "npc_catapult" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "75000" + "extra_damage" "1.0" + "plugin" "npc_giant_armored_medic" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "30000" + "extra_damage" "2.0" + "plugin" "npc_agent_61" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "0" + "health" "90000" + "extra_damage" "1.75" + "plugin" "npc_signaller" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "4" + "health" "35000" + "extra_damage" "1.5" + "plugin" "npc_ambusher" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "150000" + "extra_damage" "1.35" + "plugin" "npc_demon_possesed_armor" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "35000" + "extra_damage" "1.5" + "plugin" "npc_protector" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "4" + "health" "50000" + "extra_damage" "2.0" + "plugin" "npc_contracted_motivator" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "3" + "health" "25000" + "extra_damage" "1.35" + "plugin" "npc_hardener" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "4" + "health" "50000" + "extra_damage" "2.0" + "plugin" "npc_contracted_motivator" + "spawn" "home_attackerspawn" + } + "1.5" + { + "count" "2" + "health" "275000" + "extra_damage" "1.5" + "plugin" "npc_demolitionist" + "spawn" "home_attackerspawn" + } + "0.0" + { + "count" "3" + "health" "35000" + "extra_damage" "1.0" + "plugin" "npc_airraider" + "spawn" "home_attackerspawn" + } + } + "Freeplay" + { + // Needed key + } +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/shared/status_effects.sp b/addons/sourcemod/scripting/shared/status_effects.sp index 22ed645e9e..74545cec75 100644 --- a/addons/sourcemod/scripting/shared/status_effects.sp +++ b/addons/sourcemod/scripting/shared/status_effects.sp @@ -3024,6 +3024,20 @@ void StatusEffects_Victoria() data.SlotPriority = 0; data.HudDisplay_Func = AmmoTM_Visual_Hud_Func; StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Buffweiser"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), "BEER"); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), "BEER"); //BEEEEEERRRRR + //-1.0 means unused + data.DamageTakenMulti = 0.5; //50% less damage taken + data.DamageDealMulti = 1.0; //x2 dmg + data.Positive = true; + data.ShouldScaleWithPlayerCount = true; + data.ElementalLogic = false; + data.HudDisplay_Func = INVALID_FUNCTION; + data.Slot = 0; //0 means ignored + data.SlotPriority = 0; //if its higher, then the lower version is entirely ignored. + StatusEffect_AddGlobal(data); } stock bool NpcStats_VictorianCallToArms(int victim) diff --git a/addons/sourcemod/scripting/zombie_riot/npc.sp b/addons/sourcemod/scripting/zombie_riot/npc.sp index 4c995e06d6..802200f609 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc.sp @@ -705,6 +705,18 @@ void NPC_ConfigSetup() Harrison_OnMapStart_NPC(); Castellan_OnMapStart_NPC(); +//construction2 Victorians + Demolitionist_OnMapStart_NPC(); + Chemical_Specialist_OnMapStart_NPC(); + Victorian_Protector_OnMapStart_NPC(); + ChemicalSpreader_OnMapStart_NPC(); + Zapmarker_OnMapStart_NPC(); + ArmoredMedic_OnMapStart_NPC(); + Airraider_OnMapStart_NPC(); + Victorian_Headhunter_OnMapStart_NPC(); + Victorian_Resource_Collector_OnMapStart_NPC(); + Gasleader_OnMapStart_NPC(); + //special Invisible_TRIGGER_OnMapStart_NPC();//It is currently used as a trigger for the Victoria Factory. CaptinoBaguettus_OnMapStart_NPC();//Captino Meinus Follower @@ -2351,6 +2363,18 @@ Action NpcSpecificOnTakeDamage(int victim, int &attacker, int &inflictor, float #include "npc/raidmode_bosses/victoria/npc_harrison.sp" #include "npc/raidmode_bosses/victoria/npc_castellan.sp" +//construction2 Victorian +#include "npc/construction/construction2/victorians/npc_demolitionist.sp" +#include "npc/construction/construction2/victorians/npc_chemical_specialist.sp" +#include "npc/construction/construction2/victorians/npc_protector.sp" +#include "npc/construction/construction2/victorians/npc_chemical_spreader.sp" +#include "npc/construction/construction2/victorians/npc_zapmarker.sp" +#include "npc/construction/construction2/victorians/npc_giant_armored_medic.sp" +#include "npc/construction/construction2/victorians/npc_airraider.sp" +#include "npc/construction/construction2/victorians/npc_headhunter.sp" +#include "npc/construction/construction2/victorians/npc_boltbag.sp" +#include "npc/construction/construction2/victorians/npc_gasleader.sp" + //Matrix Enemies #include "npc/matrix/15/npc_agentalan.sp" #include "npc/matrix/15/npc_agentalexander.sp" diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_airraider.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_airraider.sp new file mode 100644 index 0000000000..5388beaa18 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_airraider.sp @@ -0,0 +1,545 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + ")vo/soldier_negativevocalization01.mp3", + ")vo/soldier_negativevocalization02.mp3", + ")vo/soldier_negativevocalization03.mp3", + ")vo/soldier_negativevocalization04.mp3", + ")vo/soldier_negativevocalization05.mp3", + ")vo/soldier_negativevocalization06.mp3", +}; + +static const char g_HurtSounds[][] = { + "vo/soldier_painsharp01.mp3", + "vo/soldier_painsharp02.mp3", + "vo/soldier_painsharp03.mp3", + "vo/soldier_painsharp04.mp3", + "vo/soldier_painsharp05.mp3", + "vo/soldier_painsharp06.mp3", + "vo/soldier_painsharp07.mp3", + "vo/soldier_painsharp08.mp3" +}; + + +static const char g_IdleAlertedSounds[][] = { + "vo/soldier_dominationsniper13.mp3", + "vo/soldier_dominationsniper01.mp3", + "vo/compmode/cm_soldier_pregamefirst_04.mp3", + "vo/compmode/cm_soldier_pregamefirst_05.mp3", + "vo/compmode/cm_soldier_pregamefirst_06.mp3", +}; + +static const char g_RangedAttackSounds[][] = { + "weapons/airstrike_fire_01.wav", + "weapons/airstrike_fire_02.wav", + "weapons/airstrike_fire_03.wav", +}; +static const char g_MeleeAttackSounds[][] = { + "weapons/shotgun_shoot.wav", +}; + +void Airraider_OnMapStart_NPC() +{ + for (int i = 0; i < (sizeof(g_DeathSounds)); i++) { PrecacheSound(g_DeathSounds[i]); } + for (int i = 0; i < (sizeof(g_HurtSounds)); i++) { PrecacheSound(g_HurtSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSound(g_IdleAlertedSounds[i]); } + for (int i = 0; i < (sizeof(g_RangedAttackSounds)); i++) { PrecacheSound(g_RangedAttackSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeAttackSounds)); i++) { PrecacheSound(g_MeleeAttackSounds[i]); } + PrecacheModel("models/player/soldier.mdl"); + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Airraider"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_airraider"); + strcopy(data.Icon, sizeof(data.Icon), "soldine"); + data.IconCustom = true; + data.Flags = 0; + data.Category = Type_Victoria; + data.Func = ClotSummon; + NPC_Add(data); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return Airraider(vecPos, vecAng, team); +} + +methodmap Airraider < CClotBody +{ + property int i_GunMode + { + public get() { return i_TimesSummoned[this.index]; } + public set(int TempValueForProperty) { i_TimesSummoned[this.index] = TempValueForProperty; } + } + property float f_AirraiderRocketJumpCD_Wearoff + { + public get() { return fl_AttackHappensMaximum[this.index]; } + public set(float TempValueForProperty) { fl_AttackHappensMaximum[this.index] = TempValueForProperty; } + } + property bool b_AirraiderRocketJump + { + public get() { return b_NextRangedBarrage_OnGoing[this.index]; } + public set(bool TempValueForProperty) { b_NextRangedBarrage_OnGoing[this.index] = TempValueForProperty; } + } + public void PlayIdleAlertSound() + { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(12.0, 24.0); + + } + + public void PlayHurtSound() + { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + + EmitSoundToAll(g_HurtSounds[GetRandomInt(0, sizeof(g_HurtSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME); + + } + + public void PlayDeathSound() + { + EmitSoundToAll(g_DeathSounds[GetRandomInt(0, sizeof(g_DeathSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME); + } + + public void PlayRangedSound() + { + EmitSoundToAll(g_RangedAttackSounds[GetRandomInt(0, sizeof(g_RangedAttackSounds) - 1)], this.index, SNDCHAN_AUTO, BOSS_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME); + } + public void PlayShotgunSound() + { + EmitSoundToAll(g_MeleeAttackSounds[GetRandomInt(0, sizeof(g_MeleeAttackSounds) - 1)], this.index, SNDCHAN_AUTO, NORMAL_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME); + } + + + public Airraider(float vecPos[3], float vecAng[3], int ally) + { + Airraider npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "7500", ally)); + + i_NpcWeight[npc.index] = 1; + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_MP_RUN_PRIMARY"); + if(iActivity > 0) npc.StartActivity(iActivity); + + SetVariantInt(2); + AcceptEntityInput(npc.index, "SetBodyGroup"); + + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + func_NPCDeath[npc.index] = Airraider_NPCDeath; + func_NPCOnTakeDamage[npc.index] = Airraider_OnTakeDamage; + func_NPCThink[npc.index] = Airraider_ClotThink; + + npc.StartPathing(); + npc.m_flSpeed = 250.0; + npc.i_GunMode = 1; + npc.m_flGravityMulti = 0.35; + + npc.Anger = true; + npc.b_AirraiderRocketJump = true; + + npc.m_flNextRangedAttack = GetGameTime(npc.index) + 3.0; + npc.f_AirraiderRocketJumpCD_Wearoff = GetGameTime(npc.index) + 1.0; + b_NpcIsInvulnerable[npc.index] = true; + npc.m_bTeamGlowDefault = false; + + int skin = 1; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + // Weapon + npc.m_iWearable1 = npc.EquipItem("head", "models/weapons/c_models/c_rocketlauncher/c_rocketlauncher.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + + npc.m_iWearable2 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_paratooper_pack/c_paratrooper_parachute.mdl"); + SetVariantString("3.0"); + AcceptEntityInput(npc.m_iWearable2, "SetModelScale"); + + npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/player/items/soldier/dec2014_skullcap/dec2014_skullcap.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable3, "SetModelScale"); + + npc.m_iWearable4 = npc.EquipItem("head", "models/workshop/player/items/all_class/dec15_gift_bringer/dec15_gift_bringer_soldier.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable4, "SetModelScale"); + + npc.m_iWearable5 = npc.EquipItem("head", "models/workshop/player/items/soldier/fall17_attack_packs/fall17_attack_packs.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable5, "SetModelScale"); + + npc.m_iWearable6 = npc.EquipItem("head", "models/workshop/player/items/soldier/hwn2025_seamanns/hwn2025_seamanns.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable6, "SetModelScale"); + + npc.m_iWearable7 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_paratooper_pack/c_paratrooper_pack.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable7, "SetModelScale"); + + SetEntProp(npc.m_iWearable2, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable4, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable5, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable6, Prop_Send, "m_nSkin", skin); + + NpcColourCosmetic_ViaPaint(npc.m_iWearable3, 1581885); + NpcColourCosmetic_ViaPaint(npc.m_iWearable4, 1581885); + NpcColourCosmetic_ViaPaint(npc.m_iWearable5, 1581885); + + SetEntPropFloat(npc.index, Prop_Send, "m_fadeMinDist", 1.0); + SetEntPropFloat(npc.index, Prop_Send, "m_fadeMaxDist", 1.0); + SetEntPropFloat(npc.m_iWearable1, Prop_Send, "m_fadeMinDist", 1.0); + SetEntPropFloat(npc.m_iWearable1, Prop_Send, "m_fadeMaxDist", 1.0); + SetEntPropFloat(npc.m_iWearable2, Prop_Send, "m_fadeMinDist", 1.0); + SetEntPropFloat(npc.m_iWearable2, Prop_Send, "m_fadeMaxDist", 1.0); + SetEntPropFloat(npc.m_iWearable3, Prop_Send, "m_fadeMinDist", 1.0); + SetEntPropFloat(npc.m_iWearable3, Prop_Send, "m_fadeMaxDist", 1.0); + SetEntPropFloat(npc.m_iWearable4, Prop_Send, "m_fadeMinDist", 1.0); + SetEntPropFloat(npc.m_iWearable4, Prop_Send, "m_fadeMaxDist", 1.0); + SetEntPropFloat(npc.m_iWearable5, Prop_Send, "m_fadeMinDist", 1.0); + SetEntPropFloat(npc.m_iWearable5, Prop_Send, "m_fadeMaxDist", 1.0); + SetEntPropFloat(npc.m_iWearable6, Prop_Send, "m_fadeMinDist", 1.0); + SetEntPropFloat(npc.m_iWearable6, Prop_Send, "m_fadeMaxDist", 1.0); + SetEntPropFloat(npc.m_iWearable7, Prop_Send, "m_fadeMinDist", 1.0); + SetEntPropFloat(npc.m_iWearable7, Prop_Send, "m_fadeMaxDist", 1.0); + + SetVariantString("deploy_idle"); + AcceptEntityInput(npc.m_iWearable2, "SetAnimation"); + + return npc; + } +} + +public void Airraider_ClotThink(int iNPC) +{ + Airraider npc = view_as(iNPC); + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + npc.Update(); + + if(!npc.IsOnGround()) + { + npc.m_flRangedArmor = 2.0; + } + else + { + npc.m_flRangedArmor = 1.0; + } + + if(npc.b_AirraiderRocketJump) + { + if(IsValidEntity(npc.m_iTeamGlow)) + RemoveEntity(npc.m_iTeamGlow); + npc.StopPathing(); + if(npc.f_AirraiderRocketJumpCD_Wearoff < GetGameTime(npc.index)) + { + TeleportDiversioToRandLocation(npc.index); + static float flPos[3]; + GetEntPropVector(npc.index, Prop_Data, "m_vecAbsOrigin", flPos); + flPos[2] += 3000.0; + PluginBot_Jump(npc.index, flPos); + SetEntPropFloat(npc.m_iWearable1, Prop_Send, "m_fadeMinDist", 1.0); + SetEntPropFloat(npc.m_iWearable1, Prop_Send, "m_fadeMaxDist", 1.0); + npc.f_AirraiderRocketJumpCD_Wearoff = GetGameTime(npc.index) + 1.0; + npc.b_AirraiderRocketJump = false; + } + return; + } + else if(npc.IsOnGround()) + { + if(npc.f_AirraiderRocketJumpCD_Wearoff < GetGameTime(npc.index)) + { + npc.Anger = false; + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + npc.i_GunMode = 0; + npc.m_flGravityMulti = 1.0; + } + } + else + { + if(npc.Anger && npc.f_AirraiderRocketJumpCD_Wearoff < GetGameTime(npc.index)) + { + b_NpcIsInvulnerable[npc.index] = false; + npc.m_bTeamGlowDefault = true; + SetEntPropFloat(npc.index, Prop_Send, "m_fadeMinDist", 0.0); + SetEntPropFloat(npc.index, Prop_Send, "m_fadeMaxDist", 0.0); + SetEntPropFloat(npc.m_iWearable1, Prop_Send, "m_fadeMinDist", 0.0); + SetEntPropFloat(npc.m_iWearable1, Prop_Send, "m_fadeMaxDist", 0.0); + if(IsValidEntity(npc.m_iWearable2)) + { + SetEntPropFloat(npc.m_iWearable2, Prop_Send, "m_fadeMinDist", 0.0); + SetEntPropFloat(npc.m_iWearable2, Prop_Send, "m_fadeMaxDist", 0.0); + } + SetEntPropFloat(npc.m_iWearable3, Prop_Send, "m_fadeMinDist", 0.0); + SetEntPropFloat(npc.m_iWearable3, Prop_Send, "m_fadeMaxDist", 0.0); + SetEntPropFloat(npc.m_iWearable4, Prop_Send, "m_fadeMinDist", 0.0); + SetEntPropFloat(npc.m_iWearable4, Prop_Send, "m_fadeMaxDist", 0.0); + SetEntPropFloat(npc.m_iWearable5, Prop_Send, "m_fadeMinDist", 0.0); + SetEntPropFloat(npc.m_iWearable5, Prop_Send, "m_fadeMaxDist", 0.0); + SetEntPropFloat(npc.m_iWearable6, Prop_Send, "m_fadeMinDist", 0.0); + SetEntPropFloat(npc.m_iWearable6, Prop_Send, "m_fadeMaxDist", 0.0); + SetEntPropFloat(npc.m_iWearable7, Prop_Send, "m_fadeMinDist", 0.0); + SetEntPropFloat(npc.m_iWearable7, Prop_Send, "m_fadeMaxDist", 0.0); + } + } + + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + + if(npc.m_flNextThinkTime > GetGameTime(npc.index)) + { + return; + } + + npc.m_flNextThinkTime = GetGameTime(npc.index) + 0.1; + + if(npc.m_flGetClosestTargetTime < GetGameTime(npc.index)) + { + npc.m_iTarget = GetClosestTarget(npc.index); + npc.m_flGetClosestTargetTime = GetGameTime(npc.index) + GetRandomRetargetTime(); + } + + if(IsValidEnemy(npc.index, npc.m_iTarget)) + { + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + if(flDistanceToTarget < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + } + AirraiderSelfDefense(npc,GetGameTime(npc.index), npc.m_iTarget, flDistanceToTarget); + } + else + { + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + + AirraiderAnimationChange(npc); + npc.PlayIdleAlertSound(); +} + +public Action Airraider_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + Airraider npc = view_as(victim); + + if(attacker <= 0) + return Plugin_Continue; + + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + + return Plugin_Changed; +} + +public void Airraider_NPCDeath(int entity) +{ + Airraider npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + if(IsValidEntity(npc.m_iWearable7)) + RemoveEntity(npc.m_iWearable7); + if(IsValidEntity(npc.m_iWearable6)) + RemoveEntity(npc.m_iWearable6); + if(IsValidEntity(npc.m_iWearable8)) + RemoveEntity(npc.m_iWearable8); + if(IsValidEntity(npc.m_iWearable5)) + RemoveEntity(npc.m_iWearable5); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + +} +/* + + +*/ +void AirraiderAnimationChange(Airraider npc) +{ + switch(npc.i_GunMode) + { + case 1: //primary + { + if (npc.IsOnGround()) + { + if(npc.m_iChanged_WalkCycle != 1) + { + ResetAirraiderWeapon(npc, 1); + SetVariantInt(2); + AcceptEntityInput(npc.index, "SetBodyGroup"); + npc.m_bisWalking = true; + npc.m_iChanged_WalkCycle = 1; + npc.SetActivity("ACT_MP_RUN_PRIMARY"); + npc.StartPathing(); + } + } + else + { + if(npc.m_iChanged_WalkCycle != 2) + { + ResetAirraiderWeapon(npc, 1); + SetVariantInt(2); + AcceptEntityInput(npc.index, "SetBodyGroup"); + npc.m_bisWalking = false; + npc.m_iChanged_WalkCycle = 2; + npc.SetActivity("ACT_MP_JUMP_FLOAT_PRIMARY"); + npc.StartPathing(); + } + } + } + case 0: //Secondary + { + if (npc.IsOnGround()) + { + if(npc.m_iChanged_WalkCycle != 3) + { + ResetAirraiderWeapon(npc, 0); + SetVariantInt(2); + AcceptEntityInput(npc.index, "SetBodyGroup"); + npc.m_bisWalking = true; + npc.m_iChanged_WalkCycle = 3; + npc.SetActivity("ACT_MP_RUN_SECONDARY"); + npc.StartPathing(); + } + } + else + { + if(npc.m_iChanged_WalkCycle != 4) + { + ResetAirraiderWeapon(npc, 0); + SetVariantInt(2); + AcceptEntityInput(npc.index, "SetBodyGroup"); + npc.m_bisWalking = false; + npc.m_iChanged_WalkCycle = 4; + npc.SetActivity("ACT_MP_JUMP_FLOAT_SECONDARY"); + npc.StartPathing(); + } + } + } + } + +} + +void AirraiderSelfDefense(Airraider npc, float gameTime, int target, float distance) +{ + if(!npc.Anger) + { + npc.i_GunMode = 0; //Imma use my shotgun now + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 3.0)) + { + int Enemy_I_See = Can_I_See_Enemy(npc.index, npc.m_iTarget); + if(IsValidEnemy(npc.index, Enemy_I_See) && gameTime > npc.m_flNextRangedAttack) + { + npc.AddGesture("ACT_MP_ATTACK_STAND_SECONDARY"); + npc.m_iTarget = Enemy_I_See; + npc.PlayShotgunSound(); + float vecTarget[3]; WorldSpaceCenter(target, vecTarget); + npc.FaceTowards(vecTarget, 20000.0); + Handle swingTrace; + if(npc.DoSwingTrace(swingTrace, target, { 9999.0, 9999.0, 9999.0 })) + { + target = TR_GetEntityIndex(swingTrace); + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + float origin[3], angles[3]; + view_as(npc.m_iWearable1).GetAttachment("muzzle", origin, angles); + ShootLaser(npc.m_iWearable1, "bullet_tracer02_blue", origin, vecHit, false ); + npc.m_flNextMeleeAttack = gameTime + 0.75; + + if(IsValidEnemy(npc.index, target)) + { + float damageDealt = 90.0; + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 2.0; + + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_BULLET, -1, _, vecHit); + } + npc.m_flNextRangedAttack = gameTime + 0.50; + } + delete swingTrace; + } + } + return; + } + npc.i_GunMode = 1; //rocket! + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 900.0)) + { + if(gameTime > npc.m_flNextRangedAttack) + { + if(Can_I_See_Enemy_Only(npc.index, target)) + { + float projectile_speed = 1000.0; + float DamageRocket = 30.0; + float vPredictedPos[3]; + PredictSubjectPositionForProjectiles(npc, target, projectile_speed, _,vPredictedPos); + + npc.FaceTowards(vPredictedPos, 20000.0); + //Play attack anim + npc.AddGesture("ACT_MP_ATTACK_STAND_PRIMARY"); + + npc.PlayRangedSound(); + npc.FireRocket(vPredictedPos, DamageRocket, projectile_speed, "models/weapons/w_models/w_rocket_airstrike/w_rocket_airstrike.mdl"); + npc.m_flNextRangedAttack = gameTime + 0.30; + } + } + } + return; +} + +void ResetAirraiderWeapon(Airraider npc, int weapon_Type) +{ + if(IsValidEntity(npc.m_iWearable1)) + { + RemoveEntity(npc.m_iWearable1); + } + switch(weapon_Type) + { + case 1: + { + npc.m_iWearable1 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_atom_launcher/c_atom_launcher.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + } + case 0: + { + npc.m_iWearable1 = npc.EquipItem("head", "models/weapons/c_models/c_reserve_shooter/c_reserve_shooter.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + } + } +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_boltbag.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_boltbag.sp new file mode 100644 index 0000000000..a529055273 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_boltbag.sp @@ -0,0 +1,297 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + ")physics/metal/metal_canister_impact_hard1.wav", + ")physics/metal/metal_canister_impact_hard2.wav", + ")physics/metal/metal_canister_impact_hard3.wav", +}; + +static const char g_HurtSounds[][] = { + "weapons/sentry_damage1.wav", + "weapons/sentry_damage2.wav", + "weapons/sentry_damage3.wav", + "weapons/sentry_damage4.wav" +}; + +static const char g_IdleAlertedSounds[][] = { + "npc/scanner/scanner_alert1.wav" +}; + +static const char g_MeleeAttackSounds[][] = { + "weapons/machete_swing.wav", +}; + +static const char g_MeleeHitSounds[][] = { + "weapons/neon_sign_hit_01.wav", + "weapons/neon_sign_hit_02.wav", + "weapons/neon_sign_hit_03.wav", + "weapons/neon_sign_hit_04.wav" +}; + +static const char g_SapperHitSounds[][] = { + "weapons/rescue_ranger_charge_01.wav", + "weapons/rescue_ranger_charge_02.wav", +}; + +void Victorian_Resource_Collector_OnMapStart_NPC() +{ + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Resource Collector"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_resource_collector"); + strcopy(data.Icon, sizeof(data.Icon), "victoria_ironshield"); + data.IconCustom = false; + data.Flags = 0; + data.Category = Type_Victoria; + data.Precache = ClotPrecache; + data.Func = ClotSummon; + NPC_Add(data); +} + +static void ClotPrecache() +{ + PrecacheSoundArray(g_DeathSounds); + PrecacheSoundArray(g_HurtSounds); + PrecacheSoundArray(g_IdleAlertedSounds); + PrecacheSoundArray(g_MeleeAttackSounds); + PrecacheSoundArray(g_MeleeHitSounds); + PrecacheSoundArray(g_SapperHitSounds); + PrecacheModel("models/bots/bot_worker/bot_worker.mdl"); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int ally) +{ + return ResourceCollector(vecPos, vecAng, ally); +} + +methodmap ResourceCollector < CClotBody +{ + public void PlayIdleAlertSound() + { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 150); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(12.0, 24.0); + } + public void PlayHurtSound() + { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + + EmitSoundToAll(g_HurtSounds[GetRandomInt(0, sizeof(g_HurtSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 125); + } + public void PlayDeathSound() + { + EmitSoundToAll(g_DeathSounds[GetRandomInt(0, sizeof(g_DeathSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 130); + } + public void PlayMeleeSound() + { + EmitSoundToAll(g_MeleeAttackSounds[GetRandomInt(0, sizeof(g_MeleeAttackSounds) - 1)], this.index, SNDCHAN_AUTO, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + public void PlayMeleeHitSound() + { + EmitSoundToAll(g_MeleeHitSounds[GetRandomInt(0, sizeof(g_MeleeHitSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + public void PlaySapperHitSound() + { + EmitSoundToAll(g_SapperHitSounds[GetRandomInt(0, sizeof(g_SapperHitSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + + } + + public ResourceCollector(float vecPos[3], float vecAng[3], int ally) + { + ResourceCollector npc = view_as(CClotBody(vecPos, vecAng, "models/bots/bot_worker/bot_worker.mdl", "0.8", "9500", ally)); + + i_NpcWeight[npc.index] = 1; + + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_METAL; + npc.m_iNpcStepVariation = 0; + + func_NPCDeath[npc.index] = view_as(ResourceCollector_NPCDeath); + func_NPCOnTakeDamage[npc.index] = view_as(ResourceCollector_OnTakeDamage); + func_NPCThink[npc.index] = view_as(ResourceCollector_ClotThink); + + b_DoGibThisNpc[npc.index] = true; + b_DissapearOnDeath[npc.index] = true; + + //IDLE + npc.m_iState = 0; + npc.m_flGetClosestTargetTime = 0.0; + npc.StartPathing(); + npc.m_flSpeed = 300.0; + + npc.m_flRangedArmor = 0.7; + + int skin = 1; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + //npc.m_iWearable1 = npc.EquipItemSeperate("models/workshop/player/items/engineer/sum19_brain_interface/sum19_brain_interface.mdl",_,skin,1.9,-120.0); + + return npc; + } +} + +static void ResourceCollector_ClotThink(int iNPC) +{ + ResourceCollector npc = view_as(iNPC); + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + npc.Update(); + + if(npc.m_blPlayHurtAnimation) + { + npc.PlayHurtSound(); + } + + if(npc.m_flNextThinkTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextThinkTime = GetGameTime(npc.index) + 0.1; + + if(npc.m_flGetClosestTargetTime < GetGameTime(npc.index)) + { + npc.m_iTarget = GetClosestTarget(npc.index); + npc.m_flGetClosestTargetTime = GetGameTime(npc.index) + GetRandomRetargetTime(); + } + if(NpcStats_VictorianCallToArms(npc.index)) + { + npc.m_flSpeed = 400.0; + } + else + { + npc.m_flSpeed = 300.0; + } + + if(IsValidEnemy(npc.index, npc.m_iTarget)) + { + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + if(flDistanceToTarget < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + } + ResourceCollectorSelfDefense(npc,GetGameTime(npc.index), npc.m_iTarget, flDistanceToTarget); + } + else + { + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + + + npc.PlayIdleAlertSound(); +} + +static Action ResourceCollector_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + ResourceCollector npc = view_as(victim); + + if(attacker <= 0) + return Plugin_Continue; + + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + + return Plugin_Changed; +} + +static void ResourceCollector_NPCDeath(int entity) +{ + ResourceCollector npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + float VecDeath[3]; WorldSpaceCenter(npc.index, VecDeath); + ParticleEffectAt(VecDeath, "ExplosionCore_buildings", 0.5); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); +} + +static void ResourceCollectorSelfDefense(ResourceCollector npc, float gameTime, int target, float distance) +{ + if(npc.m_flAttackHappens) + { + if(npc.m_flAttackHappens < gameTime) + { + npc.m_flAttackHappens = 0.0; + + Handle swingTrace; + float VecEnemy[3]; WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 15000.0); + if(npc.DoSwingTrace(swingTrace, npc.m_iTarget)) + { + + target = TR_GetEntityIndex(swingTrace); + + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + + if(IsValidEnemy(npc.index, target)) + { + float damageDealt = 50.0; + + if(ShouldNpcDealBonusDamage(target)) + { + damageDealt *= 5.0; + if(NpcStats_VictorianCallToArms(npc.index)) + damageDealt *= 2.0; + } + + + int DamageType = DMG_CLUB; + + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DamageType, -1, _, vecHit); + + // Hit sound + if(ShouldNpcDealBonusDamage(target)) + npc.PlaySapperHitSound(); + else + npc.PlayMeleeHitSound(); + } + } + delete swingTrace; + } + } + + if(gameTime > npc.m_flNextMeleeAttack) + { + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED)) + { + int Enemy_I_See; + + Enemy_I_See = Can_I_See_Enemy(npc.index, npc.m_iTarget); + + if(IsValidEnemy(npc.index, Enemy_I_See)) + { + npc.m_iTarget = Enemy_I_See; + npc.PlayMeleeSound(); + npc.AddGesture("panic",_,_,_,1.0); + + npc.m_flAttackHappens = gameTime + 0.15; + npc.m_flDoingAnimation = gameTime + 0.15; + npc.m_flNextMeleeAttack = gameTime + 1.0; + } + } + } +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_specialist.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_specialist.sp new file mode 100644 index 0000000000..6b89a6c451 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_specialist.sp @@ -0,0 +1,351 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + ")vo/engineer_negativevocalization01.mp3", + ")vo/engineer_negativevocalization02.mp3", + ")vo/engineer_negativevocalization03.mp3", + ")vo/engineer_negativevocalization04.mp3", + ")vo/engineer_negativevocalization05.mp3", + ")vo/engineer_negativevocalization06.mp3", + ")vo/engineer_negativevocalization07.mp3", + ")vo/engineer_negativevocalization08.mp3", + ")vo/engineer_negativevocalization09.mp3", + ")vo/engineer_negativevocalization10.mp3", + ")vo/engineer_negativevocalization11.mp3", + ")vo/engineer_negativevocalization12.mp3", +}; + +static const char g_HurtSounds[][] = { + "vo/engineer_painsharp01.mp3", + "vo/engineer_painsharp02.mp3", + "vo/engineer_painsharp03.mp3", + "vo/engineer_painsharp04.mp3", + "vo/engineer_painsharp05.mp3", + "vo/engineer_painsharp06.mp3", + "vo/engineer_painsharp07.mp3", + "vo/engineer_painsharp08.mp3" +}; + + +static const char g_IdleAlertedSounds[][] = { + "vo/engineer_mvm_mannhattan_gate_atk01.mp3", + "vo/engineer_mvm_mannhattan_gate_atk02.mp3", + "vo/engineer_mvm_mannhattan_gate_atk03.mp3", +}; + +static const char g_RangeAttackSounds[] = "weapons/ar2/fire1.wav"; + +void Chemical_Specialist_OnMapStart_NPC() +{ + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Chemical Specialist"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_chemical_specialist"); + strcopy(data.Icon, sizeof(data.Icon), "victoria_shotgunner"); + data.IconCustom = true; + data.Flags = 0; + data.Category = Type_Victoria; + data.Precache = ClotPrecache; + data.Func = ClotSummon; + int id = NPC_Add(data); + Rogue_Paradox_AddWinterNPC(id); +} + +static void ClotPrecache() +{ + PrecacheSoundArray(g_DeathSounds); + PrecacheSoundArray(g_HurtSounds); + PrecacheSoundArray(g_IdleAlertedSounds); + PrecacheSound(g_RangeAttackSounds); + PrecacheModel("models/player/engineer.mdl"); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int ally) +{ + return Chemical_Specialist(vecPos, vecAng, ally); +} + +methodmap Chemical_Specialist < CClotBody +{ + public void PlayIdleAlertSound() + { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(12.0, 24.0); + } + public void PlayHurtSound() + { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + EmitSoundToAll(g_HurtSounds[GetRandomInt(0, sizeof(g_HurtSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + } + public void PlayDeathSound() + { + EmitSoundToAll(g_DeathSounds[GetRandomInt(0, sizeof(g_DeathSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + public void PlayRangeSound() + { + EmitSoundToAll(g_RangeAttackSounds[GetRandomInt(0, sizeof(g_RangeAttackSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 85); + } + + public Chemical_Specialist(float vecPos[3], float vecAng[3], int ally) + { + Chemical_Specialist npc = view_as(CClotBody(vecPos, vecAng, "models/player/engineer.mdl", "1.0", "7500", ally)); + + i_NpcWeight[npc.index] = 2; + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_MP_RUN_SECONDARY"); + if(iActivity > 0) npc.StartActivity(iActivity); + + SetVariantInt(3); + AcceptEntityInput(npc.index, "SetBodyGroup"); + + npc.m_flRangedArmor = 0.9; + npc.m_flMeleeArmor = 0.7; + + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + func_NPCDeath[npc.index] = Chemical_Specialist_NPCDeath; + func_NPCOnTakeDamage[npc.index] = Chemical_Specialist_OnTakeDamage; + func_NPCThink[npc.index] = Chemical_Specialist_ClotThink; + + //IDLE + KillFeed_SetKillIcon(npc.index, "panic_attack"); + npc.m_iState = 0; + npc.m_flGetClosestTargetTime = 0.0; + npc.StartPathing(); + npc.m_flSpeed = 230.0; + + int skin = 1; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable1 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_pro_smg/c_pro_smg.mdl"); + npc.m_iWearable2 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_uberneedle/c_uberneedle.mdl"); + SetEntProp(npc.m_iWearable2, Prop_Send, "m_nSkin", 1); + npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/player/items/engineer/invasion_life_support_system/invasion_life_support_system.mdl"); + SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", 1); + npc.m_iWearable4 = npc.EquipItem("head", "models/workshop/player/items/engineer/hwn2024_mannhattan_protect/hwn2024_mannhattan_protect.mdl"); + SetEntProp(npc.m_iWearable4, Prop_Send, "m_nSkin", 1); + npc.m_iWearable5 = npc.EquipItem("head", "models/workshop/player/items/engineer/hwn2024_nuclear_necessity/hwn2024_nuclear_necessity.mdl"); + SetEntProp(npc.m_iWearable5, Prop_Send, "m_nSkin", 1); + npc.m_iWearable6 = npc.EquipItem("head", "models/workshop/player/items/engineer/hwn2024_contaminated_carryall/hwn2024_contaminated_carryall.mdl"); + SetEntProp(npc.m_iWearable6, Prop_Send, "m_nSkin", 1); + + return npc; + } +} + +static void Chemical_Specialist_ClotThink(int iNPC) +{ + Chemical_Specialist npc = view_as(iNPC); + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + npc.Update(); + + if(npc.m_bAllowBackWalking) + { + if(IsValidEnemy(npc.index, npc.m_iTarget)) + { + float WorldSpaceVec[3]; WorldSpaceCenter(npc.m_iTarget, WorldSpaceVec); + npc.FaceTowards(WorldSpaceVec, 150.0); + } + } + + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + if(npc.m_flNextThinkTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextThinkTime = GetGameTime(npc.index) + 0.1; + + if(npc.m_flGetClosestTargetTime < GetGameTime(npc.index)) + { + npc.m_iTarget = GetClosestTarget(npc.index); + npc.m_flGetClosestTargetTime = GetGameTime(npc.index) + GetRandomRetargetTime(); + } + + Elemental_ClearDamage(npc.index); + + if(IsValidEnemy(npc.index, npc.m_iTarget)) + { + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + switch(Chemical_SpecialistSelfDefense(npc,GetGameTime(npc.index), npc.m_iTarget, flDistanceToTarget)) + { + case 0: + { + npc.m_bAllowBackWalking = false; + //Get the normal prediction code. + if(flDistanceToTarget < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + } + } + case 1: + { + npc.m_bAllowBackWalking = true; + float vBackoffPos[3]; + BackoffFromOwnPositionAndAwayFromEnemy(npc, npc.m_iTarget,_,vBackoffPos); + npc.SetGoalVector(vBackoffPos, true); //update more often, we need it + } + } + } + else + { + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleAlertSound(); +} + +static Action Chemical_Specialist_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + Chemical_Specialist npc = view_as(victim); + + if(attacker <= 0) + return Plugin_Continue; + + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + + return Plugin_Changed; +} + +static void Chemical_Specialist_NPCDeath(int entity) +{ + Chemical_Specialist npc = view_as(entity); + if(!npc.m_bGib) + npc.PlayDeathSound(); + + if(IsValidEntity(npc.m_iWearable6)) + RemoveEntity(npc.m_iWearable6); + if(IsValidEntity(npc.m_iWearable5)) + RemoveEntity(npc.m_iWearable5); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); +} + +static int Chemical_SpecialistSelfDefense(Chemical_Specialist npc, float gameTime, int target, float distance) +{ + if(gameTime > npc.m_flNextMeleeAttack) + { + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 2.5)) + { + int Enemy_I_See = Can_I_See_Enemy(npc.index, target); + if(IsValidEnemy(npc.index, Enemy_I_See)) + { + npc.AddGesture("ACT_MP_ATTACK_STAND_SECONDARY"); + npc.m_iTarget = Enemy_I_See; + npc.PlayRangeSound(); + float vecTarget[3]; WorldSpaceCenter(target, vecTarget); + npc.FaceTowards(vecTarget, 20000.0); + Handle swingTrace; + if(npc.DoSwingTrace(swingTrace, target, { 9999.0, 9999.0, 9999.0 })) + { + target = TR_GetEntityIndex(swingTrace); + + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + float origin[3], angles[3]; + view_as(npc.index).GetAttachment("effect_hand_r", origin, angles); + ShootLaser(npc.index, "bullet_tracer02_blue", origin, vecHit, false ); + npc.m_flNextMeleeAttack = gameTime + 0.5; + + if(IsValidEnemy(npc.index, target)) + { + float damageDealt = 35.0; + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 3.0; + int ElementalDamge = 25; + if(NpcStats_VictorianCallToArms(npc.index)) + ElementalDamge *= 2; + Elemental_AddNervousDamage(target, npc.index, ElementalDamge); + + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_BULLET, -1, _, vecHit); + } + } + delete swingTrace; + } + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 3.5)) + { + //target is too far, try to close in + return 0; + } + else if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 1.5)) + { + if(Can_I_See_Enemy_Only(npc.index, target)) + { + //target is too close, try to keep distance + return 1; + } + } + return 0; + } + else + { + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 3.5)) + { + //target is too far, try to close in + return 0; + } + else if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 1.5)) + { + if(Can_I_See_Enemy_Only(npc.index, target)) + { + //target is too close, try to keep distance + return 1; + } + } + } + } + else + { + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 3.5)) + { + //target is too far, try to close in + return 0; + } + else if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 1.5)) + { + if(Can_I_See_Enemy_Only(npc.index, target)) + { + //target is too close, try to keep distance + return 1; + } + } + } + return 0; +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_spreader.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_spreader.sp new file mode 100644 index 0000000000..0d2eec1fe2 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_spreader.sp @@ -0,0 +1,341 @@ +#pragma semicolon 1 +#pragma newdecls required + + +static const char g_DeathSounds[][] = { + "vo/pyro_paincrticialdeath01.mp3", + "vo/pyro_paincrticialdeath02.mp3", + "vo/pyro_paincrticialdeath03.mp3", +}; + +static const char g_HurtSounds[][] = { + "vo/pyro_painsharp01.mp3", + "vo/pyro_painsharp02.mp3", + "vo/pyro_painsharp03.mp3", + "vo/pyro_painsharp04.mp3", + "vo/pyro_painsharp05.mp3", +}; +static const char g_IdleAlertedSounds[][] = { + "vo/taunts/pyro_taunts01.mp3", + "vo/taunts/pyro_taunts02.mp3", + "vo/taunts/pyro_taunts03.mp3", +}; + + +void ChemicalSpreader_OnMapStart_NPC() +{ + for (int i = 0; i < (sizeof(g_DeathSounds)); i++) { PrecacheSound(g_DeathSounds[i]); } + for (int i = 0; i < (sizeof(g_HurtSounds)); i++) { PrecacheSound(g_HurtSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSound(g_IdleAlertedSounds[i]); } + PrecacheSound("weapons/flame_thrower_loop.wav"); + PrecacheSound("weapons/flame_thrower_pilot.wav"); + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Chemical Spreader"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_chemical_spreader"); + strcopy(data.Icon, sizeof(data.Icon), "victoria_pulverizer"); + data.IconCustom = true; + data.Flags = 0; + data.Category = Type_Victoria; + data.Func = ClotSummon; + int id = NPC_Add(data); + Rogue_Paradox_AddWinterNPC(id); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return ChemicalSpreader(vecPos, vecAng, team); +} + +methodmap ChemicalSpreader < CClotBody +{ + + property int i_GunMode + { + public get() { return i_TimesSummoned[this.index]; } + public set(int TempValueForProperty) { i_TimesSummoned[this.index] = TempValueForProperty; } + } + public void PlayIdleAlertSound() + { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(12.0, 24.0); + + } + + public void PlayHurtSound() + { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + + EmitSoundToAll(g_HurtSounds[GetRandomInt(0, sizeof(g_HurtSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + + } + + property float m_flPulveriserAttackDelay + { + public get() { return fl_AbilityOrAttack[this.index][1]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][1] = TempValueForProperty; } + } + public void PlayDeathSound() + { + EmitSoundToAll(g_DeathSounds[GetRandomInt(0, sizeof(g_DeathSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + public void PlayMinigunSound(bool Shooting) + { + if(Shooting) + { + if(this.i_GunMode != 0) + { + StopSound(this.index, SNDCHAN_STATIC, "weapons/flame_thrower_pilot.wav"); + EmitSoundToAll("weapons/flame_thrower_loop.wav", this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, 1.20); + } + this.i_GunMode = 0; + } + else + { + if(this.i_GunMode != 1) + { + StopSound(this.index, SNDCHAN_STATIC, "weapons/flame_thrower_loop.wav"); + EmitSoundToAll("weapons/flame_thrower_pilot.wav", this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, 1.20); + } + this.i_GunMode = 1; + } + } + + public ChemicalSpreader(float vecPos[3], float vecAng[3], int ally) + { + ChemicalSpreader npc = view_as(CClotBody(vecPos, vecAng, "models/player/pyro.mdl", "1.0", "3000", ally)); + + i_NpcWeight[npc.index] = 1; + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_MP_RUN_PRIMARY"); + if(iActivity > 0) npc.StartActivity(iActivity); + + SetVariantInt(0); + AcceptEntityInput(npc.index, "SetBodyGroup"); + + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + func_NPCDeath[npc.index] = view_as(ChemicalSpreader_NPCDeath); + func_NPCOnTakeDamage[npc.index] = view_as(ChemicalSpreader_OnTakeDamage); + func_NPCThink[npc.index] = view_as(ChemicalSpreader_ClotThink); + + + + npc.StartPathing(); + npc.m_flSpeed = 280.0; + + + int skin = 1; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable1 = npc.EquipItem("head", "models/weapons/c_models/c_drg_phlogistinator/c_drg_phlogistinator.mdl"); + npc.m_iWearable2 = npc.EquipItem("head", "models/player/items/pyro/drg_pyro_fueltank.mdl"); + npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/player/items/all_class/dec15_patriot_peak/dec15_patriot_peak_pyro.mdl"); + npc.m_iWearable4 = npc.EquipItem("head", "models/workshop/player/items/pyro/spr18_hot_case/spr18_hot_case.mdl"); + npc.m_iWearable5 = npc.EquipItem("head", "models/workshop/player/items/pyro/dec25_veterans_visor/dec25_veterans_visor.mdl"); + + SetEntProp(npc.m_iWearable1, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable2, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable4, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable5, Prop_Send, "m_nSkin", skin); + + SetVariantString("1.5"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + SetVariantString("2.0"); + AcceptEntityInput(npc.m_iWearable2, "SetModelScale"); + + NpcColourCosmetic_ViaPaint(npc.m_iWearable3, 6637376); + NpcColourCosmetic_ViaPaint(npc.m_iWearable4, 1581885); + NpcColourCosmetic_ViaPaint(npc.m_iWearable5, 15787660); + + return npc; + } +} + +public void ChemicalSpreader_ClotThink(int iNPC) +{ + ChemicalSpreader npc = view_as(iNPC); + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + npc.Update(); + + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + if(npc.m_flNextThinkTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextThinkTime = GetGameTime(npc.index) + 0.1; + + if(npc.m_flGetClosestTargetTime < GetGameTime(npc.index)) + { + npc.m_iTarget = GetClosestTarget(npc.index); + npc.m_flGetClosestTargetTime = GetGameTime(npc.index) + GetRandomRetargetTime(); + } + + if(IsValidEnemy(npc.index, npc.m_iTarget)) + { + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + if(flDistanceToTarget < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + } + ChemicalSpreaderSelfDefense(npc); + } + else + { + npc.PlayMinigunSound(false); + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleAlertSound(); +} + +public Action ChemicalSpreader_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + ChemicalSpreader npc = view_as(victim); + + if(attacker <= 0) + return Plugin_Continue; + + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + + return Plugin_Changed; +} + +public void ChemicalSpreader_NPCDeath(int entity) +{ + ChemicalSpreader npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + StopSound(npc.index, SNDCHAN_STATIC, "weapons/flame_thrower_loop.wav"); + StopSound(npc.index, SNDCHAN_STATIC, "weapons/flame_thrower_pilot.wav"); + StopSound(npc.index, SNDCHAN_STATIC, "weapons/flame_thrower_loop.wav"); + StopSound(npc.index, SNDCHAN_STATIC, "weapons/flame_thrower_pilot.wav"); + + if(IsValidEntity(npc.m_iWearable5)) + RemoveEntity(npc.m_iWearable5); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + +} + +void ChemicalSpreaderSelfDefense(ChemicalSpreader npc) +{ + if(npc.m_flPulveriserAttackDelay > GetGameTime(npc.index)) + { + return; + } + npc.m_flPulveriserAttackDelay = GetGameTime(npc.index) + 0.2; + int target; + target = npc.m_iTarget; + //some Ranged units will behave differently. + //not this one. + float vecTarget[3]; WorldSpaceCenter(target, vecTarget); + bool SpinSound = true; + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + if(flDistanceToTarget < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 5.0)) + { + npc.PlayMinigunSound(true); + SpinSound = false; + npc.FaceTowards(vecTarget, 20000.0); + int projectile = npc.FireParticleRocket(vecTarget, 8.0, 1000.0, 150.0, "unusual_icetornado_blue_parent", true); + SDKUnhook(projectile, SDKHook_StartTouch, Rocket_Particle_StartTouch); + int particle = EntRefToEntIndex(i_WandParticle[projectile]); + CreateTimer(0.5, Timer_RemoveEntity, EntIndexToEntRef(projectile), TIMER_FLAG_NO_MAPCHANGE); + CreateTimer(0.5, Timer_RemoveEntity, EntIndexToEntRef(particle), TIMER_FLAG_NO_MAPCHANGE); + + SDKHook(projectile, SDKHook_StartTouch, ChemicalSpreader_Rocket_Particle_StartTouch); + } + if(SpinSound) + npc.PlayMinigunSound(false); +} + + + +public void ChemicalSpreader_Rocket_Particle_StartTouch(int entity, int target) +{ + if(target > 0 && target < MAXENTITIES) //did we hit something??? + { + int owner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity"); + if(!IsValidEntity(owner)) + { + owner = 0; + } + + int inflictor = h_ArrowInflictorRef[entity]; + if(inflictor != -1) + inflictor = EntRefToEntIndex(h_ArrowInflictorRef[entity]); + + if(inflictor == -1) + inflictor = owner; + + float ProjectileLoc[3]; + GetEntPropVector(entity, Prop_Data, "m_vecAbsOrigin", ProjectileLoc); + float DamageDeal = fl_rocket_particle_dmg[entity]; + if(ShouldNpcDealBonusDamage(target)) + DamageDeal *= h_BonusDmgToSpecialArrow[entity]; + + + SDKHooks_TakeDamage(target, owner, inflictor, DamageDeal, DMG_BULLET|DMG_PREVENT_PHYSICS_FORCE, -1); //acts like a kinetic rocket + + Elemental_AddNervousDamage(target, owner, 25, true); + int particle = EntRefToEntIndex(i_WandParticle[entity]); + if(IsValidEntity(particle)) + { + RemoveEntity(particle); + } + } + else + { + int particle = EntRefToEntIndex(i_WandParticle[entity]); + //we uhh, missed? + if(IsValidEntity(particle)) + { + RemoveEntity(particle); + } + } + RemoveEntity(entity); +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_demolitionist.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_demolitionist.sp new file mode 100644 index 0000000000..0119c91680 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_demolitionist.sp @@ -0,0 +1,330 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + "vo/heavy_negativevocalization01.mp3", + "vo/heavy_negativevocalization02.mp3", + "vo/heavy_negativevocalization03.mp3" +}; + +static const char g_HurtSounds[][] = { + "vo/heavy_cartmovingforwardoffense14.mp3", +}; + +static const char g_IdleAlertedSounds[][] = { + "vo/heavy_specialcompleted03.mp3", + "vo/heavy_specialcompleted02.mp3", + "vo/taunts/heavy_taunts13.mp3", + "vo/taunts/heavy_taunts17.mp3", +}; + +static const char g_MeleeAttackSounds[][] = { + "weapons/demo_sword_swing1.wav", + "weapons/demo_sword_swing2.wav", + "weapons/demo_sword_swing3.wav" +}; + +static const char g_MeleeHitSounds[] = "weapons/bat_baseball_hit_flesh.wav"; + +static const char g_ExplosionSounds[] = "weapons/explode1.wav"; + + +void Demolitionist_OnMapStart_NPC() +{ + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Demolitionist"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_demolitionist"); + strcopy(data.Icon, sizeof(data.Icon), "victoria_bulldozer"); + data.IconCustom = true; + data.Flags = 0; + data.Category = Type_Victoria; + data.Precache = ClotPrecache; + data.Func = ClotSummon; + NPC_Add(data); +} + +static void ClotPrecache() +{ + PrecacheSoundArray(g_DeathSounds); + PrecacheSoundArray(g_HurtSounds); + PrecacheSoundArray(g_IdleAlertedSounds); + PrecacheSoundArray(g_MeleeAttackSounds); + PrecacheSound(g_MeleeHitSounds); + PrecacheModel("models/player/heavy.mdl"); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int ally) +{ + return Demolitionist(vecPos, vecAng, ally); +} + +methodmap Demolitionist < CClotBody +{ + public void PlayIdleAlertSound() + { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(12.0, 24.0); + } + public void PlayHurtSound() + { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + + EmitSoundToAll(g_HurtSounds[GetRandomInt(0, sizeof(g_HurtSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + } + public void PlayDeathSound() + { + EmitSoundToAll(g_DeathSounds[GetRandomInt(0, sizeof(g_DeathSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + } + public void PlayMeleeSound() + { + EmitSoundToAll(g_MeleeAttackSounds[GetRandomInt(0, sizeof(g_MeleeAttackSounds) - 1)], this.index, SNDCHAN_AUTO, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + } + public void PlayMeleeHitSound() + { + EmitSoundToAll(g_MeleeHitSounds, this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 90); + } + public void PlayExplosionSound() + { + EmitSoundToAll(g_ExplosionSounds, this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + } + + + public Demolitionist(float vecPos[3], float vecAng[3], int ally) + { + Demolitionist npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.4", "12000", ally, .isGiant = true)); + + i_NpcWeight[npc.index] = 3; + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_MP_RUN_MELEE_ALLCLASS"); + if(iActivity > 0) npc.StartActivity(iActivity); + + func_NPCDeath[npc.index] = Demolitionist_NPCDeath; + func_NPCOnTakeDamage[npc.index] = Demolitionist_OnTakeDamage; + func_NPCThink[npc.index] = Demolitionist_ClotThink; + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + SetVariantInt(4); + AcceptEntityInput(npc.index, "SetBodyGroup"); + + npc.m_flRangedArmor = 1.0; + npc.m_flMeleeArmor = 0.75; + + //IDLE + KillFeed_SetKillIcon(npc.index, "the_maul"); + npc.m_iState = 0; + npc.m_flGetClosestTargetTime = 0.0; + npc.StartPathing(); + npc.m_flSpeed = 150.0; + + int skin = 1; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable1 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_powerjack/c_powerjack.mdl"); + SetVariantString("1.25"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + + npc.m_iWearable2 = npc.EquipItem("head", "models/weapons/c_models/c_sr3_punch/c_sr3_punch.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable2, "SetModelScale"); + + npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/player/items/heavy/sbox2014_leftover_trap/sbox2014_leftover_trap.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable3, "SetModelScale"); + + npc.m_iWearable4 = npc.EquipItem("head", "models/workshop/player/items/soldier/soldier_warpig/soldier_warpig.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable4, "SetModelScale"); + SetEntProp(npc.m_iWearable4, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable5 = npc.EquipItem("head", "models/player/items/heavy/heavy_wolf_chest.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable5, "SetModelScale"); + SetEntProp(npc.m_iWearable5, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable6 = npc.EquipItem("head", "models/workshop/player/items/heavy/dec25_punchers_polar_style3/dec25_punchers_polar_style3.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable5, "SetModelScale"); + SetEntProp(npc.m_iWearable6, Prop_Send, "m_nSkin", skin); + + return npc; + } +} + +static void Demolitionist_ClotThink(int iNPC) +{ + Demolitionist npc = view_as(iNPC); + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + npc.Update(); + + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + if(npc.m_flNextThinkTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextThinkTime = GetGameTime(npc.index) + 0.1; + + if(npc.m_flGetClosestTargetTime < GetGameTime(npc.index)) + { + npc.m_iTarget = GetClosestTarget(npc.index); + npc.m_flGetClosestTargetTime = GetGameTime(npc.index) + GetRandomRetargetTime(); + } + + if(IsValidEnemy(npc.index, npc.m_iTarget)) + { + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + if(flDistanceToTarget < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + } + DemolitionistSelfDefense(npc,GetGameTime(npc.index), npc.m_iTarget, flDistanceToTarget); + } + else + { + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleAlertSound(); +} + +static Action Demolitionist_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + Demolitionist npc = view_as(victim); + + if(attacker <= 0) + return Plugin_Continue; + + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + return Plugin_Changed; +} + +static void Demolitionist_NPCDeath(int entity) +{ + Demolitionist npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + if(IsValidEntity(npc.m_iWearable6)) + RemoveEntity(npc.m_iWearable6); + if(IsValidEntity(npc.m_iWearable5)) + RemoveEntity(npc.m_iWearable5); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + +} + +static void DemolitionistSelfDefense(Demolitionist npc, float gameTime, int target, float distance) +{ + if(npc.m_flAttackHappens) + { + if(npc.m_flAttackHappens < gameTime) + { + npc.m_flAttackHappens = 0.0; + Handle swingTrace; + float VecEnemy[3]; WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 15000.0); + if(npc.DoSwingTrace(swingTrace, npc.m_iTarget,_,_,_,1)) //Big range, but dont ignore buildings if somehow this doesnt count as a raid to be sure. + { + target = TR_GetEntityIndex(swingTrace); + + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + + if(IsValidEnemy(npc.index, target)) + { + float damageDealt = 75.0; + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 8.0; + + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_CLUB, -1, _, vecHit); + Explode_Logic_Custom(40.0, -1, npc.index, -1, VecEnemy, 125.0, _, 0.75, true, _, false, _, Demolitionist_ExplodeHit); + ParticleEffectAt(VecEnemy, "ExplosionCore_buildings", 0.5); + + // Hit sound + npc.PlayMeleeHitSound(); + npc.PlayExplosionSound(); + } + } + delete swingTrace; + } + } + + if(gameTime > npc.m_flNextMeleeAttack) + { + if(distance < (GIANT_ENEMY_MELEE_RANGE_FLOAT_SQUARED)) + { + int Enemy_I_See; + Enemy_I_See = Can_I_See_Enemy(npc.index, npc.m_iTarget); + if(IsValidEnemy(npc.index, Enemy_I_See)) + { + npc.m_iTarget = Enemy_I_See; + npc.PlayMeleeSound(); + npc.AddGesture("ACT_MP_ATTACK_STAND_MELEE_ALLCLASS",_,_,_,0.5); + npc.m_flAttackHappens = gameTime + 0.45; + npc.m_flDoingAnimation = gameTime + 0.45; + npc.m_flNextMeleeAttack = gameTime + 1.5; + } + } + } +} + +static void Demolitionist_ExplodeHit(int entity, int victim, float damage, int weapon) +{ + float vecHit[3]; WorldSpaceCenter(victim, vecHit); + if(GetTeam(entity) != GetTeam(victim)) + { + int inflictor = h_ArrowInflictorRef[entity]; + if(inflictor != -1) + inflictor = EntRefToEntIndex(h_ArrowInflictorRef[entity]); + + if(inflictor == -1) + inflictor = entity; + damage = 200.0; + if(ShouldNpcDealBonusDamage(victim)) + damage *= 8.0; + if(NpcStats_VictorianCallToArms(entity)) + damage *= 2.0; + SDKHooks_TakeDamage(victim, entity, inflictor, damage, DMG_BLAST, -1, _, vecHit); + } +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_gasleader.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_gasleader.sp new file mode 100644 index 0000000000..21a20a29ec --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_gasleader.sp @@ -0,0 +1,770 @@ +#pragma semicolon 1 +#pragma newdecls required + +static char g_DeathSounds[][] = { + "npc/combine_soldier/die1.wav", + "npc/combine_soldier/die2.wav", + "npc/combine_soldier/die3.wav", +}; + +static char g_HurtSound[][] = { + "npc/combine_soldier/pain1.wav", + "npc/combine_soldier/pain2.wav", + "npc/combine_soldier/pain3.wav", +}; + +static const char g_IdleAlertedSounds[][] = { + "npc/combine_soldier/vo/alert1.wav", + "npc/combine_soldier/vo/bouncerbouncer.wav", + "npc/combine_soldier/vo/boomer.wav", + "npc/combine_soldier/vo/contactconfim.wav", +}; + +static const char g_MeleeHitSounds[][] = { + "weapons/blade_slice_2.wav", + "weapons/blade_slice_3.wav", + "weapons/blade_slice_4.wav", +}; + +static const char g_MegaMeleeHitSounds[][] = { + "items/cart_explode.wav", +}; + +static const char g_RangeAttackSounds[] = "weapons/pistol/pistol_fire2.wav"; + +static const char g_MeleeAttackSounds[] = "weapons/demo_sword_swing1.wav"; + +void Gasleader_OnMapStart_NPC() +{ + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Victoria Gasleader"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_gasleader"); + strcopy(data.Icon, sizeof(data.Icon), "victoria_aviator"); + data.IconCustom = true; + data.Flags = 0; + data.Category = Type_Victoria; + data.Precache = ClotPrecache; + data.Func = ClotSummon; + NPC_Add(data); +} + +static void ClotPrecache() +{ + PrecacheSoundArray(g_DeathSounds); + PrecacheSoundArray(g_HurtSound); + PrecacheSoundArray(g_IdleAlertedSounds); + PrecacheSoundArray(g_MeleeHitSounds); + PrecacheSoundArray(g_MegaMeleeHitSounds); + PrecacheSound(g_RangeAttackSounds); + PrecacheSound(g_MeleeAttackSounds); + PrecacheModel(COMBINE_CUSTOM_MODEL); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return Gasleader(vecPos, vecAng, team); +} +methodmap Gasleader < CClotBody +{ + property int m_iAlliesDied + { + public get() { return i_OverlordComboAttack[this.index]; } + public set(int TempValueForProperty) { i_OverlordComboAttack[this.index] = TempValueForProperty; } + } + property int m_iAlliesMaxDeath + { + public get() { return i_TimesSummoned[this.index]; } + public set(int TempValueForProperty) { i_TimesSummoned[this.index] = TempValueForProperty; } + } + property float m_flPercentageAngry + { + public get() { return fl_Charge_delay[this.index]; } + public set(float TempValueForProperty) { fl_Charge_delay[this.index] = TempValueForProperty; } + } + public void PlayIdleAlertSound() + { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(12.0, 24.0); + } + public void PlayHurtSound() + { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + + EmitSoundToAll(g_HurtSound[GetRandomInt(0, sizeof(g_HurtSound) - 1)], this.index, SNDCHAN_VOICE, BOSS_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME); + } + public void PlayDeathSound() + { + EmitSoundToAll(g_DeathSounds[GetRandomInt(0, sizeof(g_DeathSounds) - 1)], this.index, SNDCHAN_VOICE, BOSS_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME); + } + public void PlayMeleeSound() + { + EmitSoundToAll(g_MeleeAttackSounds, this.index, SNDCHAN_AUTO, BOSS_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME); + } + public void PlayRangedSound() { + EmitSoundToAll(g_RangeAttackSounds, this.index, _, BOSS_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME); + } + public void PlayMeleeHitSound() + { + EmitSoundToAll(g_MeleeHitSounds[GetRandomInt(0, sizeof(g_MeleeHitSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME); + } + public void PlayMegaMeleeHitSound() + { + EmitSoundToAll(g_MegaMeleeHitSounds[GetRandomInt(0, sizeof(g_MegaMeleeHitSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME, 80); + } + + property int i_GunMode + { + public get() { return i_TimesSummoned[this.index]; } + public set(int TempValueForProperty) { i_TimesSummoned[this.index] = TempValueForProperty; } + } + + public Gasleader(float vecPos[3], float vecAng[3], int ally) + { + Gasleader npc = view_as(CClotBody(vecPos, vecAng, COMBINE_CUSTOM_MODEL, "1.55", "50000", ally)); + + i_NpcWeight[npc.index] = 3; + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + SetVariantInt(3); + AcceptEntityInput(npc.index, "SetBodyGroup"); + + npc.SetActivity("ACT_CUSTOM_WALK_EAGLE"); + npc.m_iChanged_WalkCycle = 2; + + npc.m_flNextMeleeAttack = 0.0; + npc.m_flNextRangedAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + func_NPCDeath[npc.index] = view_as(Gasleader_NPCDeath); + func_NPCOnTakeDamage[npc.index] = view_as(Gasleader_OnTakeDamage); + func_NPCThink[npc.index] = view_as(Gasleader_ClotThink); + //func_NPCDeathForward[npc.index] = Gasleader_AllyDeath; + + npc.i_GunMode = 0; + + npc.StartPathing(); + npc.m_flSpeed = 250.0; + float MaxAlliesDeath = 50.0; + MaxAlliesDeath *= MultiGlobalEnemy; + npc.m_iAlliesMaxDeath = RoundToCeil(MaxAlliesDeath); + npc.m_flRangedSpecialDelay = GetGameTime(npc.index) + 0.5; + + npc.m_flPercentageAngry = 0.0; + npc.m_iAlliesDied = 0; + npc.Anger = false; + + if(!IsValidEntity(RaidBossActive)) + { + RaidModeScaling = 0.0; //just a safety net + RaidBossActive = EntIndexToEntRef(npc.index); + RaidModeTime = GetGameTime(npc.index) + 9000.0; + RaidAllowsBuildings = true; + } + + int skin = 1; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable1 = npc.EquipItem("weapon_bone", "models/weapons/w_pistol.mdl"); + SetVariantString("1.5"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + + npc.m_iWearable2 = npc.EquipItem("thorns_backpack_1", "models/weapons/c_models/c_claymore/c_claymore_xmas.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable2, "SetModelScale"); + + npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/player/items/engineer/hwn2024_contaminated_carryall/hwn2024_contaminated_carryall.mdl"); + SetVariantString("3.0"); + AcceptEntityInput(npc.m_iWearable3, "SetModelScale"); + + npc.m_iWearable4 = npc.EquipItem("head", "models/workshop/player/items/soldier/tw_soldierbot_armor/tw_soldierbot_armor.mdl"); + SetVariantString("1.33"); + AcceptEntityInput(npc.m_iWearable4, "SetModelScale"); + + npc.m_iWearable5 = npc.EquipItem("head","models/workshop/player/items/soldier/thief_soldier_helmet/thief_soldier_helmet.mdl"); + SetVariantString("1.25"); + AcceptEntityInput(npc.m_iWearable5, "SetModelScale"); + + npc.m_iWearable6 = ParticleEffectAt_Parent(vecPos, "utaunt_tarotcard_blue_glow", npc.index, "m_vecAbsOrigin", {0.0,0.0,0.0}); + + npc.m_iWearable9 = ParticleEffectAt_Parent(vecPos, "utaunt_poweraura_blue_beam", npc.index, "m_vecAbsOrigin", {0.0,0.0,0.0}); + + SetEntProp(npc.m_iWearable2, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable4, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable5, Prop_Send, "m_nSkin", skin); + + npc.m_iOverlordComboAttack = 0; + + + return npc; + } +} + +static void Gasleader_ClotThink(int iNPC) +{ + Gasleader npc = view_as(iNPC); + float gametime = GetGameTime(npc.index); + if(npc.m_flNextDelayTime > gametime) + return; + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + npc.Update(); + + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + GrantEntityArmor(iNPC, true, 0.33, 0.5, 0); //50% res armor + + if(npc.Anger == false) + { + float vecMe[3]; WorldSpaceCenter(npc.index, vecMe); + float radius = 500.0; + GasleaderEffect(npc.index, radius); + if(gametime > npc.m_flRangedSpecialDelay) + { + Explode_Logic_Custom(10.0, -1, npc.index, -1, vecMe, radius, _, 0.75, true, _, false, _, Gasleader_ExplodePost); + npc.m_flRangedSpecialDelay = gametime + 0.5; + } + float VecI[3]; WorldSpaceCenter(npc.index, VecI); + for(int entitycount; entitycount gametime) + return; + npc.m_flNextThinkTime = gametime + 0.1; + + if(npc.m_flGetClosestTargetTime (victim); + + if(attacker <= 0) + return Plugin_Continue; + + if(npc.m_flArmorCount <= 0.0 && npc.Anger == false) + { + npc.Anger = true; + npc.m_iChanged_WalkCycle = 2; + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + } + + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + + return Plugin_Changed; +} + +static void Gasleader_NPCDeath(int entity) +{ + Gasleader npc = view_as(entity); + if(!npc.m_bGib) + npc.PlayDeathSound(); + + if(IsValidEntity(npc.m_iWearable9)) + RemoveEntity(npc.m_iWearable9); + if(IsValidEntity(npc.m_iWearable8)) + RemoveEntity(npc.m_iWearable8); + if(IsValidEntity(npc.m_iWearable7)) + RemoveEntity(npc.m_iWearable7); + if(IsValidEntity(npc.m_iWearable6)) + RemoveEntity(npc.m_iWearable6); + if(IsValidEntity(npc.m_iWearable5)) + RemoveEntity(npc.m_iWearable5); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); +} + +static int GasleaderSelfDefense(Gasleader npc, float gameTime, float distance) +{ + if(distance < NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED *3.0 || npc.m_flAttackHappenswillhappen) + { + if(npc.m_flNextMeleeAttack < gameTime) + { + if(!npc.m_flAttackHappenswillhappen) + { + if(npc.m_iOverlordComboAttack <= 2) + { + /* + switch(GetRandomInt(0,1)) + { + case 0: + { + npc.AddGesture("ACT_BLADEDANCE_ATTACK_LEFT"); + } + case 1: + { + npc.AddGesture("ACT_MILITIA_ATTACK"); + } + } + */ + npc.AddGesture("ACT_MILITIA_ATTACK"); + } + else + { + npc.AddGesture("ACT_SEABORN_ATTACK_TOOL_1"); + } + npc.PlayMeleeSound(); + npc.m_flAttackHappens = gameTime +0.25; + npc.m_flDoingAnimation = gameTime + 0.25; + npc.m_flAttackHappens_bullshit = gameTime + 0.35; + npc.m_flAttackHappenswillhappen = true; + } + if(npc.m_flAttackHappens < gameTime && npc.m_flAttackHappens_bullshit >= gameTime && npc.m_flAttackHappenswillhappen) + { + int HowManyEnemeisAoeMelee = 64; + Handle swingTrace; + float VecEnemy[3]; WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 20000.0); + npc.DoSwingTrace(swingTrace, npc.m_iTarget,_,_,_,1,_,HowManyEnemeisAoeMelee); + delete swingTrace; + for (int counter = 1; counter <= HowManyEnemeisAoeMelee; counter++) + { + if (i_EntitiesHitAoeSwing_NpcSwing[counter] > 0) + { + if(IsValidEntity(i_EntitiesHitAoeSwing_NpcSwing[counter])) + { + int target = i_EntitiesHitAoeSwing_NpcSwing[counter]; + float damageDealt = 115.0; + int ElementalDamage = 30; + if(NpcStats_VictorianCallToArms(npc.index)) + ElementalDamage *= 2; + if(ShouldNpcDealBonusDamage(target)) + damageDealt*=10.0; + if(npc.m_iOverlordComboAttack <= 2) + { + npc.m_iOverlordComboAttack++; + Elemental_AddNervousDamage(target, npc.index, ElementalDamage, true); + npc.PlayMeleeHitSound(); + npc.m_flNextMeleeAttack = gameTime + 0.65; + } + else + { + damageDealt *= 3.0; + npc.m_iOverlordComboAttack = 0; + ElementalDamage *= 3; + Elemental_AddNervousDamage(target, npc.index, ElementalDamage, true); + if(IsValidClient(target) && !HasSpecificBuff(target, "Fluid Movement")) + { + TF2_StunPlayer(target, 1.5, 0.5, TF_STUNFLAG_SLOWDOWN); + Client_Shake(target, 0, 25.0, 12.5, 1.5); + } + ParticleEffectAt(VecEnemy, "Explosion_ShockWave_01", 0.5); + npc.m_flNextMeleeAttack = gameTime + 1.0; + } + //damageDealt *= (npc.m_flPercentageAngry * 5.0) + 1.0; + float vecHit[3]; + WorldSpaceCenter(target, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_CLUB, -1, _, vecHit); + } + } + } + /* + int HowManyEnemeisAoeMelee = 64; + Handle swingTrace; + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget); + npc.FaceTowards(vecTarget, 20000.0); + if(npc.DoSwingTrace(swingTrace, npc.m_iTarget,_,_,_,1,_,HowManyEnemeisAoeMelee)) + { + for (int counter = 1; counter <= HowManyEnemeisAoeMelee; counter++) + { + int target = TR_GetEntityIndex(swingTrace); + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + if(IsValidEnemy(npc.index, target)) + { + float damageDealt = 100.0; + int ElementalDamage = 30; + if(NpcStats_VictorianCallToArms(npc.index)) + ElementalDamage *= 2; + if(ShouldNpcDealBonusDamage(target)) + damageDealt*=10.0; + if(npc.m_iOverlordComboAttack <= 2) + { + npc.m_iOverlordComboAttack++; + Elemental_AddNervousDamage(target, npc.index, ElementalDamage, true); + npc.PlayMeleeHitSound(); + npc.m_flNextMeleeAttack = gameTime + 0.5; + } + else + { + damageDealt *= 3.0; + npc.m_iOverlordComboAttack = 0; + ElementalDamage *= 3.1; + Elemental_AddNervousDamage(target, npc.index, ElementalDamage, true); + if(IsValidClient(target) && !HasSpecificBuff(target, "Fluid Movement")) + { + TF2_StunPlayer(target, 1.5, 0.5, TF_STUNFLAG_SLOWDOWN); + Client_Shake(target, 0, 25.0, 12.5, 1.5); + } + npc.m_flNextMeleeAttack = gameTime + 1.0; + } + damageDealt *= (npc.m_flPercentageAngry * 5.0) + 1.0; + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_CLUB, -1, _, vecHit); + } + } + } + */ + npc.m_flAttackHappenswillhappen = false; + } + else if(npc.m_flAttackHappens_bullshit < gameTime && npc.m_flAttackHappenswillhappen) + { + npc.m_flAttackHappenswillhappen = false; + npc.m_flNextMeleeAttack = gameTime + 0.1; + } + } + return 2; + } + + + if(npc.m_flNextRangedAttack < gameTime) + { + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 25.0)) + { + int Enemy_I_See = Can_I_See_Enemy(npc.index, npc.m_iTarget); + + if(IsValidEnemy(npc.index, Enemy_I_See)) + { + npc.AddGesture("ACT_DARIO_ATTACK_GUN_1"); + npc.m_iTarget = Enemy_I_See; + npc.PlayRangedSound(); + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget); + npc.FaceTowards(vecTarget, 30000.0); + Handle swingTrace; + if(npc.DoSwingTrace(swingTrace, npc.m_iTarget, { 9999.0, 9999.0, 9999.0 })) + { + int target = TR_GetEntityIndex(swingTrace); + + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + float origin[3], angles[3]; + view_as(npc.m_iWearable1).GetAttachment("muzzle", origin, angles); + ShootLaser(npc.m_iWearable1, "bullet_tracer02_blue", origin, vecHit, false ); + + if(IsValidEnemy(npc.index, target)) + { + float damageDealt = 80.0; + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 10.0; + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_BULLET, -1, _, vecHit); + if(IsValidEnemy(npc.index, target)) + ApplyStatusEffect(npc.index, target, "Cripple", NpcStats_VictorianCallToArms(npc.index) ? 7.5 : 5.0); + + } + npc.m_flNextRangedAttack = gameTime + 1.0; + } + delete swingTrace; + } + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 8.0)) + return 0; + else if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 5.0)) + { + if(Can_I_See_Enemy_Only(npc.index, npc.m_iTarget)) + return 1; + } + return 0; + } + else + { + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 8.0)) + return 0; + else if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 5.0)) + { + if(Can_I_See_Enemy_Only(npc.index, npc.m_iTarget)) + return 1; + } + } + } + else + { + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 8.0)) + return 0; + else if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 5.0)) + { + if(Can_I_See_Enemy_Only(npc.index, npc.m_iTarget)) + return 1; + } + } + return 0; +} + +void GasleaderEffect(int entity, float range) +{ + float ProjectileLoc[3]; + GetEntPropVector(entity, Prop_Data, "m_vecAbsOrigin", ProjectileLoc); + spawnRing_Vectors(ProjectileLoc, range * 2.0, 0.0, 0.0, 10.0, "materials/sprites/laserbeam.vmt", 100, 150, 255, 175, 1, 0.1, 5.0, 0.1, 3); +} + +static void Gasleader_ExplodePost(int attacker, int victim, float damage, int weapon) +{ + Elemental_AddNervousDamage(victim, attacker, 3, true); +} + +/* +public void Gasleader_AllyDeath(int self, int ally) +{ + Gasleader npc = view_as(self); + + if(GetTeam(ally) != GetTeam(self)) + { + return; + } + + float AllyPos[3]; + GetEntPropVector(ally, Prop_Data, "m_vecAbsOrigin", AllyPos); + float SelfPos[3]; + GetEntPropVector(self, Prop_Data, "m_vecAbsOrigin", SelfPos); + float flDistanceToTarget = GetVectorDistance(SelfPos, AllyPos, true); + if(flDistanceToTarget < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 25.0)) + { + npc.m_iAlliesDied += 1; + + if(npc.m_iAlliesDied >= npc.m_iAlliesMaxDeath) + { + npc.m_flPercentageAngry = 1.0; + } + else + { + npc.m_flPercentageAngry = float(npc.m_iAlliesDied) / float(npc.m_iAlliesMaxDeath); + } + } + float flPos[3]; // original + float flAng[3]; // original + if(npc.m_flPercentageAngry == 1.0) + { + if(IsValidEntity(npc.m_iWearable7)) + { + RemoveEntity(npc.m_iWearable7); + } + if(!IsValidEntity(npc.m_iWearable7)) + { + npc.GetAttachment("m_vecAbsOrigin", flPos, flAng); + npc.m_iWearable7 = ParticleEffectAt_Parent(flPos, "utaunt_poweraura_red_beam", npc.index, "m_vecAbsOrigin", {0.0,0.0,0.0}); + } + } + else if(npc.m_flPercentageAngry > 0.5) + { + if(!IsValidEntity(npc.m_iWearable7)) + { + npc.GetAttachment("m_vecAbsOrigin", flPos, flAng); + + npc.m_iWearable7 = ParticleEffectAt_Parent(flPos, "utaunt_poweraura_blue_beam", npc.index, "m_vecAbsOrigin", {0.0,0.0,0.0}); + } + } +} +*/ \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_giant_armored_medic.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_giant_armored_medic.sp new file mode 100644 index 0000000000..1baf14db7f --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_giant_armored_medic.sp @@ -0,0 +1,375 @@ +#pragma semicolon 1 +#pragma newdecls required + + +static const char g_DeathSounds[][] = { + "vo/mvm/norm/medic_mvm_paincrticialdeath01.mp3", + "vo/mvm/norm/medic_mvm_paincrticialdeath02.mp3", + "vo/mvm/norm/medic_mvm_paincrticialdeath03.mp3" +}; + +static const char g_HurtSounds[][] = { + "vo/mvm/norm/medic_mvm_painsharp01.mp3", + "vo/mvm/norm/medic_mvm_painsharp02.mp3", + "vo/mvm/norm/medic_mvm_painsharp03.mp3", + "vo/mvm/norm/medic_mvm_painsharp04.mp3" +}; + +static const char g_IdleAlertedSounds[][] = { + "vo/mvm/norm/medic_mvm_battlecry01.mp3", + "vo/mvm/norm/medic_mvm_battlecry02.mp3", + "vo/mvm/norm/medic_mvm_battlecry03.mp3", + "vo/mvm/norm/medic_mvm_battlecry04.mp3" +}; + +void ArmoredMedic_OnMapStart_NPC() +{ + for (int i = 0; i < (sizeof(g_DeathSounds)); i++) { PrecacheSound(g_DeathSounds[i]); } + for (int i = 0; i < (sizeof(g_HurtSounds)); i++) { PrecacheSound(g_HurtSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSound(g_IdleAlertedSounds[i]); } + PrecacheModel(LASERBEAM); + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Giant Armored Medibot"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_giant_armored_medic"); + strcopy(data.Icon, sizeof(data.Icon), "medic_uber"); + data.IconCustom = false; + data.Flags = MVM_CLASS_FLAG_MINIBOSS; + data.Category = Type_Expidonsa; + data.Precache = ClotPrecache; + data.Func = ClotSummon; + NPC_Add(data); +} + +static void ClotPrecache() +{ + PrecacheSoundArray(g_DeathSounds); + PrecacheSoundArray(g_HurtSounds); + PrecacheSoundArray(g_IdleAlertedSounds); + PrecacheModel("models/bots/medic/bot_medic.mdl"); + PrecacheModel(LASERBEAM); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return ArmoredMedic(vecPos, vecAng, team); +} + +methodmap ArmoredMedic < CClotBody +{ + public void PlayIdleAlertSound() { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(12.0, 24.0); + + + } + + public void PlayHurtSound() { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + + EmitSoundToAll(g_HurtSounds[GetRandomInt(0, sizeof(g_HurtSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + + } + + public void PlayDeathSound() { + + EmitSoundToAll(g_DeathSounds[GetRandomInt(0, sizeof(g_DeathSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + + public ArmoredMedic(float vecPos[3], float vecAng[3], int ally) + { + ArmoredMedic npc = view_as(CClotBody(vecPos, vecAng, "models/bots/medic/bot_medic.mdl", "1.35", "50000", ally, .isGiant = true)); + + i_NpcWeight[npc.index] = 3; + SetVariantInt(1); + AcceptEntityInput(npc.index, "SetBodyGroup"); + + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_MP_RUN_SECONDARY"); + if(iActivity > 0) npc.StartActivity(iActivity); + + + func_NPCDeath[npc.index] = ArmoredMedic_NPCDeath; + func_NPCOnTakeDamage[npc.index] = ArmoredMedic_OnTakeDamage; + func_NPCThink[npc.index] = ArmoredMedic_ClotThink; + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_METAL; + npc.m_iNpcStepVariation = 0; + + npc.m_flRangedArmor = 0.8; + npc.m_flMeleeArmor = 0.7; + + + //IDLE + npc.m_flSpeed = 150.0; + npc.m_iWearable5 = INVALID_ENT_REFERENCE; + Is_a_Medic[npc.index] = true; + + npc.m_bnew_target = false; + npc.StartPathing(); + + + int skin = 1; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + ApplyStatusEffect(npc.index, npc.index, "Clear Head", 999999.0); + ApplyStatusEffect(npc.index, npc.index, "Solid Stance", 999999.0); + ApplyStatusEffect(npc.index, npc.index, "Fluid Movement", 999999.0); + + npc.m_iWearable1 = npc.EquipItem("head", "models/workshop/player/items/engineer/spr18_cold_case/spr18_cold_case.mdl"); + SetVariantString("1.75"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + + SetEntProp(npc.m_iWearable1, Prop_Send, "m_nSkin", 1); + + npc.m_iWearable3 = npc.EquipItem("head", "models/weapons/c_models/c_proto_medigun/c_proto_medigun.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable3, "SetModelScale"); + + npc.m_iWearable2 = npc.EquipItem("head", "models/workshop/player/items/medic/robo_medic_physician_mask/robo_medic_physician_mask.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable2, "SetModelScale"); + + npc.m_iWearable6 = npc.EquipItem("head", "models/workshop/player/items/demo/sum20_hazard_headgear/sum20_hazard_headgear.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable6, "SetModelScale"); + + npc.m_iWearable7 = npc.EquipItem("head", "models/workshop/player/items/engineer/hwn2020_wavefinder/hwn2020_wavefinder.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable7, "SetModelScale"); + + SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", 1); + SetEntProp(npc.m_iWearable6, Prop_Send, "m_nSkin", 1); + SetEntProp(npc.m_iWearable7, Prop_Send, "m_nSkin", 1); + + NpcColourCosmetic_ViaPaint(npc.m_iWearable2, 15132390); + NpcColourCosmetic_ViaPaint(npc.m_iWearable6, 15132390); + NpcColourCosmetic_ViaPaint(npc.m_iWearable7, 15132390); + npc.StartPathing(); + + return npc; + } + public void StartHealing() + { + int im_iWearable3 = this.m_iWearable3; + if(im_iWearable3 != INVALID_ENT_REFERENCE) + { + this.Healing = true; + + // EmitSoundToAll("m_iWearable3s/medigun_heal.wav", this.index, SNDCHAN_m_iWearable3); + } + } + public void StopHealing() + { + int iBeam = this.m_iWearable5; + if(iBeam != INVALID_ENT_REFERENCE) + { + int iBeamTarget = GetEntPropEnt(iBeam, Prop_Send, "m_hOwnerEntity"); + if(IsValidEntity(iBeamTarget)) + { + AcceptEntityInput(iBeamTarget, "ClearParent"); + RemoveEntity(iBeamTarget); + } + + AcceptEntityInput(iBeam, "ClearParent"); + RemoveEntity(iBeam); + + EmitSoundToAll("weapons/medigun_no_target.wav", this.index, SNDCHAN_WEAPON); + + // StopSound(this.index, SNDCHAN_m_iWearable3, "m_iWearable3s/medigun_heal.wav"); + + this.Healing = false; + } + } +} + + +public void ArmoredMedic_ClotThink(int iNPC) +{ + ArmoredMedic npc = view_as(iNPC); + + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) + { + return; + } + + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + + npc.Update(); + + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + if(npc.m_flNextThinkTime > GetGameTime(npc.index)) + { + return; + } + + if(!IsValidAlly(npc.index, GetClosestAlly(npc.index))) + { + //there is no more valid ally, suicide. + SmiteNpcToDeath(npc.index); + return; + } + + npc.m_flNextThinkTime = GetGameTime(npc.index) + 0.1; + + if(npc.m_flGetClosestTargetTime < GetGameTime(npc.index)) + { + int OldAlly = npc.m_iTargetAlly; + npc.m_iTargetAlly = GetClosestAlly(npc.index,_,_,ArmoredMedic_HealCheck); + if(!IsValidAlly(npc.index, npc.m_iTargetAlly)) + npc.m_iTargetAlly = GetClosestAlly(npc.index); + + if(OldAlly != npc.m_iTargetAlly) + npc.m_bnew_target = false; + + npc.m_flGetClosestTargetTime = GetGameTime(npc.index) + 1.0; + } + + int PrimaryThreatIndex = npc.m_iTargetAlly; + if(IsValidAlly(npc.index, PrimaryThreatIndex)) + { + npc.SetGoalEntity(PrimaryThreatIndex); + float vecTarget[3]; WorldSpaceCenter(PrimaryThreatIndex, vecTarget); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + + if(flDistanceToTarget < 400000 && Can_I_See_Enemy_Only(npc.index, PrimaryThreatIndex)) + { + if(flDistanceToTarget < 72500) + { + npc.StopPathing(); + } + else + { + npc.StartPathing(); + } + if(!npc.m_bnew_target) + { + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + npc.StartHealing(); + npc.m_iWearable4 = ConnectWithBeam(npc.m_iWearable3, PrimaryThreatIndex, 255, 215, 0, 3.0, 3.0, 1.35, LASERBEAM); + npc.Healing = true; + npc.m_bnew_target = true; + } + + if(IsValidEntity(npc.m_iWearable4)) + { + SetEntityRenderColor(npc.m_iWearable4, 255, 215, 0, 255); + } + int MaxHealth = ReturnEntityMaxHealth(PrimaryThreatIndex); + if(b_thisNpcIsABoss[PrimaryThreatIndex]) + MaxHealth = RoundToCeil(float(MaxHealth) * 0.00001); + + HealEntityGlobal(npc.index, PrimaryThreatIndex, float(MaxHealth), 1.0); + + ApplyStatusEffect(PrimaryThreatIndex, PrimaryThreatIndex, "Buffweiser", 1.1); + if(NpcStats_VictorianCallToArms(npc.index)) + { + ApplyStatusEffect(npc.index, PrimaryThreatIndex, "Taurine", 1.1); + } + float WorldSpaceVec[3]; WorldSpaceCenter(PrimaryThreatIndex, WorldSpaceVec); + npc.FaceTowards(WorldSpaceVec, 2000.0); + } + else + { + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + + npc.StartPathing(); + + npc.m_bnew_target = false; + } + } + else + { + //find new target to heal rapidly + npc.m_flGetClosestTargetTime = 0.0; + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + + npc.StartPathing(); + + npc.m_bnew_target = false; + } + + if(npc.m_flGetClosestTargetTime < GetGameTime(npc.index)) + { + npc.m_iTargetAlly = GetClosestAlly(npc.index,_,_,ArmoredMedic_HealCheck); + if(!IsValidAlly(npc.index, npc.m_iTargetAlly)) + npc.m_iTargetAlly = GetClosestAlly(npc.index); + npc.m_flGetClosestTargetTime = GetGameTime(npc.index) + 1.0; + } + npc.PlayIdleAlertSound(); +} + +public Action ArmoredMedic_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &m_iWearable3, float damageForce[3], float damagePosition[3], int damagecustom) +{ + ArmoredMedic npc = view_as(victim); + + if(attacker <= 0) + return Plugin_Continue; + + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + + return Plugin_Changed; +} + +public void ArmoredMedic_NPCDeath(int entity) +{ + ArmoredMedic npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + Is_a_Medic[npc.index] = false; + if(IsValidEntity(npc.m_iWearable7)) + RemoveEntity(npc.m_iWearable7); + if(IsValidEntity(npc.m_iWearable6)) + RemoveEntity(npc.m_iWearable6); + if(IsValidEntity(npc.m_iWearable5)) + RemoveEntity(npc.m_iWearable5); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + npc.StopHealing(); +} + +public bool ArmoredMedic_HealCheck(int provider, int entity) +{ + int MaxHealth = ReturnEntityMaxHealth(entity); + MaxHealth = RoundToNearest(float(MaxHealth) * 1.49); + int Health = GetEntProp(entity, Prop_Data, "m_iHealth"); + if(MaxHealth <= Health) + return false; + + return true; +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_headhunter.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_headhunter.sp new file mode 100644 index 0000000000..2f794f7c51 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_headhunter.sp @@ -0,0 +1,449 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + "vo/sniper_negativevocalization01.mp3", + "vo/sniper_negativevocalization02.mp3", + "vo/sniper_negativevocalization03.mp3", + "vo/sniper_negativevocalization04.mp3", + "vo/sniper_negativevocalization05.mp3", + "vo/sniper_negativevocalization06.mp3", + "vo/sniper_negativevocalization07.mp3", + "vo/sniper_negativevocalization08.mp3", + "vo/sniper_negativevocalization09.mp3" +}; + +static const char g_HurtSounds[][] = { + "vo/sniper_painsharp01.mp3", + "vo/sniper_painsharp02.mp3", + "vo/sniper_painsharp03.mp3", + "vo/sniper_painsharp04.mp3", +}; +static const char g_IdleAlertedSounds[][] = { + "vo/sniper_specialcompleted01.mp3", + "vo/sniper_specialcompleted02.mp3", + "vo/sniper_specialcompleted03.mp3", + "vo/sniper_specialcompleted04.mp3", + "vo/sniper_specialcompleted05.mp3", + "vo/sniper_specialcompleted06.mp3", + "vo/sniper_specialcompleted07.mp3", + "vo/sniper_specialcompleted08.mp3", + "vo/sniper_specialcompleted09.mp3", + "vo/sniper_specialcompleted10.mp3", + "vo/sniper_specialcompleted11.mp3", + "vo/sniper_specialcompleted12.mp3", + "vo/sniper_specialcompleted13.mp3", + "vo/sniper_specialcompleted14.mp3", + "vo/sniper_specialcompleted15.mp3", + "vo/sniper_specialcompleted16.mp3", + "vo/sniper_specialcompleted17.mp3", + "vo/sniper_specialcompleted18.mp3", + "vo/sniper_specialcompleted19.mp3", + "vo/sniper_specialcompleted20.mp3", + "vo/sniper_specialcompleted21.mp3", + "vo/sniper_specialcompleted22.mp3", + "vo/sniper_specialcompleted23.mp3", + "vo/sniper_specialcompleted24.mp3", + "vo/sniper_specialcompleted25.mp3", + "vo/sniper_specialcompleted26.mp3", + "vo/sniper_specialcompleted27.mp3", + "vo/sniper_specialcompleted28.mp3", + "vo/sniper_specialcompleted29.mp3", + "vo/sniper_specialcompleted30.mp3", + "vo/sniper_specialcompleted31.mp3", + "vo/sniper_specialcompleted32.mp3", + "vo/sniper_specialcompleted33.mp3", + "vo/sniper_specialcompleted34.mp3", + "vo/sniper_specialcompleted35.mp3", + "vo/sniper_specialcompleted36.mp3", + "vo/sniper_specialcompleted37.mp3", + "vo/sniper_specialcompleted38.mp3", + "vo/sniper_specialcompleted39.mp3", + "vo/sniper_specialcompleted40.mp3", + "vo/sniper_specialcompleted41.mp3", + "vo/sniper_specialcompleted42.mp3", + "vo/sniper_specialcompleted43.mp3", + "vo/sniper_specialcompleted44.mp3", + "vo/sniper_specialcompleted45.mp3", + "vo/sniper_specialcompleted46.mp3" +}; + +static const char g_MeleeAttackSounds[][] = { + "weapons/doom_sniper_rifle.wav", +}; + + +void Victorian_Headhunter_OnMapStart_NPC() +{ + for (int i = 0; i < (sizeof(g_DeathSounds)); i++) { PrecacheSound(g_DeathSounds[i]); } + for (int i = 0; i < (sizeof(g_HurtSounds)); i++) { PrecacheSound(g_HurtSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSound(g_IdleAlertedSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeAttackSounds)); i++) { PrecacheSound(g_MeleeAttackSounds[i]); } + PrecacheModel("models/player/medic.mdl"); + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Victorian Headhunter"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_headhunter"); + strcopy(data.Icon, sizeof(data.Icon), "sniper_headshot"); + data.IconCustom = false; + data.Flags = MVM_CLASS_FLAG_SUPPORT; + data.Category = Type_Victoria; + data.Func = ClotSummon; + NPC_Add(data); +} + + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return Victorian_Headhunter(vecPos, vecAng, team); +} + +methodmap Victorian_Headhunter < CClotBody +{ + public void PlayIdleAlertSound() + { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(12.0, 24.0); + + } + + public void PlayHurtSound() + { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + + EmitSoundToAll(g_HurtSounds[GetRandomInt(0, sizeof(g_HurtSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + + } + + public void PlayDeathSound() + { + EmitSoundToAll(g_DeathSounds[GetRandomInt(0, sizeof(g_DeathSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + + public void PlayMeleeSound() + { + EmitSoundToAll(g_MeleeAttackSounds[GetRandomInt(0, sizeof(g_MeleeAttackSounds) - 1)], this.index, SNDCHAN_AUTO, 60, _, BOSS_ZOMBIE_VOLUME); + } + + public Victorian_Headhunter(float vecPos[3], float vecAng[3], int ally) + { + Victorian_Headhunter npc = view_as(CClotBody(vecPos, vecAng, "models/player/sniper.mdl", "1.0", "4000", ally)); + + i_NpcWeight[npc.index] = 1; + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_MP_RUN_PRIMARY"); + if(iActivity > 0) npc.StartActivity(iActivity); + + SetVariantInt(2); + AcceptEntityInput(npc.index, "SetBodyGroup"); + + func_NPCDeath[npc.index] = view_as(Victorian_Headhunter_NPCDeath); + func_NPCOnTakeDamage[npc.index] = view_as(Victorian_Headhunter_OnTakeDamage); + func_NPCThink[npc.index] = view_as(Victorian_Headhunter_ClotThink); + + npc.m_iChanged_WalkCycle = 0; + + if(npc.m_iChanged_WalkCycle != 1) + { + npc.m_bisWalking = true; + npc.m_iChanged_WalkCycle = 1; + npc.SetActivity("ACT_MP_RUN_PRIMARY"); + npc.StartPathing(); + npc.m_flSpeed = 200.0; + } + npc.m_flNextMeleeAttack = GetGameTime() + 1.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + + int skin = 1; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable1 = npc.EquipItem("head", "models/weapons/c_models/c_bazaar_sniper/c_bazaar_sniper.mdl"); + npc.m_iWearable2 = npc.EquipItem("head", "models/workshop/player/items/all_class/riflemans_rallycap/riflemans_rallycap_sniper.mdl"); + npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_uberneedle/c_uberneedle.mdl"); + npc.m_iWearable4 = npc.EquipItem("head", "models/workshop/player/items/sniper/xms2013_sniper_beard/xms2013_sniper_beard.mdl"); + npc.m_iWearable5 = npc.EquipItem("head", "models/workshop/player/items/sniper/sum20_jarmaments/sum20_jarmaments.mdl"); + npc.m_iWearable6 = npc.EquipItem("head", "models/workshop/player/items/sniper/dec25_sydney_shearling/dec25_sydney_shearling.mdl"); + SetEntProp(npc.m_iWearable1, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable2, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable4, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable5, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable6, Prop_Send, "m_nSkin", skin); + + NpcColourCosmetic_ViaPaint(npc.m_iWearable2, 1581885); + NpcColourCosmetic_ViaPaint(npc.m_iWearable6, 8626083); + + + TeleportDiversioToRandLocation(npc.index,_,1750.0, 1250.0); + + return npc; + } +} + +public void Victorian_Headhunter_ClotThink(int iNPC) +{ + Victorian_Headhunter npc = view_as(iNPC); + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + npc.Update(); + + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + if(npc.m_flNextThinkTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextThinkTime = GetGameTime(npc.index) + 0.1; + + if(npc.m_flGetClosestTargetTime < GetGameTime(npc.index)) + { + npc.m_iTargetWalkTo = GetClosestTarget(npc.index); + npc.m_flGetClosestTargetTime = GetGameTime(npc.index) + GetRandomRetargetTime(); + } + + if(IsValidEnemy(npc.index, npc.m_iTargetWalkTo)) + { + float vecTarget[3]; WorldSpaceCenter(npc.m_iTargetWalkTo, vecTarget); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + int ExtraBehavior = Victorian_HeadhunterSelfDefense(npc,GetGameTime(npc.index)); + + switch(ExtraBehavior) + { + case 0: + { + if(npc.m_iChanged_WalkCycle != 1) + { + npc.m_bisWalking = true; + npc.m_iChanged_WalkCycle = 1; + npc.SetActivity("ACT_MP_RUN_PRIMARY"); + npc.StartPathing(); + npc.m_flSpeed = 200.0; + } + } + case 1: + { + if(npc.m_iChanged_WalkCycle != 2) + { + npc.m_bisWalking = false; + npc.m_iChanged_WalkCycle = 2; + npc.SetActivity("ACT_MP_CROUCH_DEPLOYED_IDLE"); + npc.StopPathing(); + npc.m_flSpeed = 0.0; + } + } + } + + if(flDistanceToTarget < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTargetWalkTo,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTargetWalkTo); + } + } + else + { + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTargetWalkTo = GetClosestTarget(npc.index); + } + npc.PlayIdleAlertSound(); +} + +public Action Victorian_Headhunter_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + Victorian_Headhunter npc = view_as(victim); + + if(attacker <= 0) + return Plugin_Continue; + + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + + return Plugin_Changed; +} + +public void Victorian_Headhunter_NPCDeath(int entity) +{ + Victorian_Headhunter npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + if(IsValidEntity(npc.m_iWearable7)) + RemoveEntity(npc.m_iWearable7); + if(IsValidEntity(npc.m_iWearable6)) + RemoveEntity(npc.m_iWearable6); + if(IsValidEntity(npc.m_iWearable5)) + RemoveEntity(npc.m_iWearable5); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + +} + +int Victorian_HeadhunterSelfDefense(Victorian_Headhunter npc, float gameTime) +{ + if(!npc.m_flAttackHappens) + { + if(IsValidEnemy(npc.index,npc.m_iTarget)) + { + if(!Can_I_See_Enemy_Only(npc.index, npc.m_iTarget)) + { + npc.m_iTarget = GetClosestTarget(npc.index,_,_,_,_,_,_,true,_,_,true); + } + } + else + { + npc.m_iTarget = GetClosestTarget(npc.index,_,_,_,_,_,_,true,_,_,true); + if(!IsValidEnemy(npc.index,npc.m_iTarget)) + { + return 0; + } + } + if(!IsValidEnemy(npc.index,npc.m_iTarget)) + { + return 0; + } + } + + float VecEnemy[3]; WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 15000.0); + + static float ThrowPos[MAXENTITIES][3]; + float origin[3], angles[3]; + view_as(npc.m_iWearable1).GetAttachment("muzzle", origin, angles); + if(npc.m_flDoingAnimation > gameTime) + { + if(Can_I_See_Enemy_Only(npc.index, npc.m_iTarget)) + { + WorldSpaceCenter(npc.m_iTarget, ThrowPos[npc.index]); + float pos_npc[3]; + WorldSpaceCenter(npc.index, pos_npc); + float AngleAim[3]; + GetVectorAnglesTwoPoints(pos_npc, ThrowPos[npc.index], AngleAim); + Handle hTrace = TR_TraceRayFilterEx(pos_npc, AngleAim, MASK_SOLID, RayType_Infinite, BulletAndMeleeTrace, npc.index); + if(TR_DidHit(hTrace)) + { + TR_GetEndPosition(ThrowPos[npc.index], hTrace); + } + delete hTrace; + } + } + else + { + if(npc.m_flAttackHappens) + { + float pos_npc[3]; + WorldSpaceCenter(npc.index, pos_npc); + float AngleAim[3]; + GetVectorAnglesTwoPoints(pos_npc, ThrowPos[npc.index], AngleAim); + Handle hTrace = TR_TraceRayFilterEx(pos_npc, AngleAim, MASK_SOLID, RayType_Infinite, BulletAndMeleeTrace, npc.index); + if(TR_DidHit(hTrace)) + { + TR_GetEndPosition(ThrowPos[npc.index], hTrace); + } + delete hTrace; + } + } + if(npc.m_flAttackHappens) + { + TE_SetupBeamPoints(origin, ThrowPos[npc.index], Shared_BEAM_Laser, 0, 0, 0, 0.11, 5.0, 5.0, 0, 0.0, {0,125,125,100}, 3); + TE_SendToAll(0.0); + } + + npc.FaceTowards(ThrowPos[npc.index], 15000.0); + if(npc.m_flAttackHappens) + { + if(npc.m_flAttackHappens < gameTime) + { + npc.m_flAttackHappens = 0.0; + ShootLaser(npc.m_iWearable1, "bullet_tracer02_blue_crit", origin, ThrowPos[npc.index], false ); + float pos_npc[3]; + WorldSpaceCenter(npc.index, pos_npc); + float AngleAim[3]; + GetVectorAnglesTwoPoints(pos_npc, ThrowPos[npc.index], AngleAim); + Handle hTrace = TR_TraceRayFilterEx(pos_npc, AngleAim, MASK_SOLID, RayType_Infinite, BulletAndMeleeTrace, npc.index); + int Traced_Target = TR_GetEntityIndex(hTrace); + if(Traced_Target > 0) + { + WorldSpaceCenter(Traced_Target, ThrowPos[npc.index]); + } + else if(TR_DidHit(hTrace)) + { + TR_GetEndPosition(ThrowPos[npc.index], hTrace); + } + delete hTrace; + + int target = Can_I_See_Enemy(npc.index, npc.m_iTarget,_ ,ThrowPos[npc.index]); + npc.PlayMeleeSound(); + npc.AddGesture("ACT_MP_ATTACK_CROUCH_PRIMARY_DEPLOYED"); + if(IsValidEnemy(npc.index, target)) + { + float damageDealt = 100.0; + int elementaldamage = 50; + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 5.0; + + int weapon = GetEntPropEnt(target, Prop_Send, "m_hActiveWeapon"); + switch(i_CustomWeaponEquipLogic[weapon]) + { + case WEAPON_BATTILONS,WEAPON_OCEAN,WEAPON_ANCIENT_BANNER,WEAPON_SEABORN_MISC,WEAPON_BUFF_BANNER,WEAPON_OCEAN_PAP,WEAPON_ZEALOT_POTION,WEAPON_BUFFPOTION,WEAPON_KRITZKRIEG: + { + damageDealt *= 2.0; + elementaldamage *= 2; + } + } + + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_BULLET, -1, _, ThrowPos[npc.index]); + Elemental_AddNervousDamage(target, npc.index, elementaldamage); + } + } + } + + if(gameTime > npc.m_flNextMeleeAttack) + { + if(NpcStats_VictorianCallToArms(npc.index)) + { + npc.m_flAttackHappens = gameTime + 0.65; + } + else if(!NpcStats_VictorianCallToArms(npc.index)) + { + npc.m_flAttackHappens = gameTime + 1.00; + } + npc.m_flDoingAnimation = gameTime + 0.95; + npc.m_flNextMeleeAttack = gameTime + 2.00; + } + return 1; +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_protector.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_protector.sp new file mode 100644 index 0000000000..08dd48bd42 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_protector.sp @@ -0,0 +1,374 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + "vo/engineer_paincrticialdeath01.mp3", + "vo/engineer_paincrticialdeath02.mp3", + "vo/engineer_paincrticialdeath03.mp3", +}; + +static const char g_HurtSounds[][] = { + "vo/engineer_painsharp01.mp3", + "vo/engineer_painsharp02.mp3", + "vo/engineer_painsharp03.mp3", + "vo/engineer_painsharp04.mp3", + "vo/engineer_painsharp05.mp3", + "vo/engineer_painsharp06.mp3", + "vo/engineer_painsharp07.mp3", + "vo/engineer_painsharp08.mp3", +}; + +static const char g_IdleAlertedSounds[][] = { + "vo/engineer_battlecry01.mp3", + "vo/engineer_battlecry03.mp3", + "vo/engineer_battlecry04.mp3", + "vo/engineer_battlecry05.mp3", +}; + +static const char g_MeleeAttackSounds[][] = { + "weapons/pickaxe_swing1.wav", + "weapons/pickaxe_swing2.wav", + "weapons/pickaxe_swing3.wav", +}; + +static const char g_MeleeHitSounds[][] = { + "weapons/cleaver_hit_02.wav", + "weapons/cleaver_hit_03.wav", + "weapons/cleaver_hit_05.wav", + "weapons/cleaver_hit_06.wav", + "weapons/cleaver_hit_07.wav", +}; +static const char g_BuildSound[][] = { + "weapons/medi_shield_deploy.wav", +}; + +void Victorian_Protector_OnMapStart_NPC() +{ + for (int i = 0; i < (sizeof(g_DeathSounds)); i++) { PrecacheSound(g_DeathSounds[i]); } + for (int i = 0; i < (sizeof(g_HurtSounds)); i++) { PrecacheSound(g_HurtSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSound(g_IdleAlertedSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeAttackSounds)); i++) { PrecacheSound(g_MeleeAttackSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeHitSounds)); i++) { PrecacheSound(g_MeleeHitSounds[i]); } + for (int i = 0; i < (sizeof(g_BuildSound)); i++) { PrecacheSound(g_BuildSound[i]); } + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Victorian Protector"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_protector"); + strcopy(data.Icon, sizeof(data.Icon), "engineer"); + data.IconCustom = false; + data.Flags = 0; + data.Category = Type_Victoria; + data.Func = ClotSummon; + NPC_Add(data); +} + + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team, const char[] data) +{ + return Victorian_Protector(vecPos, vecAng, team, data); +} +methodmap Victorian_Protector < CClotBody +{ + property float m_flArmorToGive + { + public get() { return fl_AbilityOrAttack[this.index][0]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][0] = TempValueForProperty; } + } + public void PlayIdleAlertSound() + { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(12.0, 24.0); + + } + + public void PlayHurtSound() + { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + + EmitSoundToAll(g_HurtSounds[GetRandomInt(0, sizeof(g_HurtSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + + } + + public void PlayDeathSound() + { + EmitSoundToAll(g_DeathSounds[GetRandomInt(0, sizeof(g_DeathSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + + public void PlayMeleeSound() + { + EmitSoundToAll(g_MeleeAttackSounds[GetRandomInt(0, sizeof(g_MeleeAttackSounds) - 1)], this.index, SNDCHAN_AUTO, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + public void PlayMeleeHitSound() + { + EmitSoundToAll(g_MeleeHitSounds[GetRandomInt(0, sizeof(g_MeleeHitSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + public void PlayBuildSound() + { + EmitSoundToAll(g_BuildSound[GetRandomInt(0, sizeof(g_BuildSound) - 1)], this.index, SNDCHAN_STATIC, BOSS_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + EmitSoundToAll(g_BuildSound[GetRandomInt(0, sizeof(g_BuildSound) - 1)], this.index, SNDCHAN_STATIC, BOSS_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + + + public Victorian_Protector(float vecPos[3], float vecAng[3], int ally, const char[] data) + { + Victorian_Protector npc = view_as(CClotBody(vecPos, vecAng, "models/player/engineer.mdl", "1.0", "10000", ally)); + + i_NpcWeight[npc.index] = 1; + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + npc.SetActivity("ACT_MP_RUN_BUILDING"); + SetVariantInt(1); + AcceptEntityInput(npc.index, "SetBodyGroup"); + + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + npc.m_flArmorToGive = StringToFloat(data); + + func_NPCDeath[npc.index] = view_as(Victorian_Protector_NPCDeath); + func_NPCOnTakeDamage[npc.index] = view_as(Victorian_Protector_OnTakeDamage); + func_NPCThink[npc.index] = view_as(Victorian_Protector_ClotThink); + + + //IDLE + npc.m_iState = 0; + npc.m_iChanged_WalkCycle = 1; + npc.m_flGetClosestTargetTime = 0.0; + npc.StartPathing(); + npc.m_flSpeed = 225.0; + npc.Anger = false; + + + int skin = 1; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable1 = npc.EquipItem("head", "models/weapons/c_models/c_toolbox/c_toolbox.mdl"); + + npc.m_iWearable2 = npc.EquipItem("head", "models/player/items/engineer/bet_pb.mdl"); + npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/player/items/engineer/sbox2014_antarctic_researcher/sbox2014_antarctic_researcher.mdl"); + npc.m_iWearable4 = npc.EquipItem("head", "models/workshop/player/items/sniper/dec2014_hunter_ushanka/dec2014_hunter_ushanka.mdl"); + npc.m_iWearable5 = npc.EquipItem("head", "models/workshop/player/items/engineer/hwn2015_western_beard/hwn2015_western_beard.mdl"); + SetEntProp(npc.m_iWearable1, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable2, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable4, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable5, Prop_Send, "m_nSkin", skin); + + return npc; + } +} + +public void Victorian_Protector_ClotThink(int iNPC) +{ + Victorian_Protector npc = view_as(iNPC); + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + npc.Update(); + + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + GrantEntityArmor(iNPC, true, 0.5, 0.0, 0); + + if(npc.m_flNextThinkTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextThinkTime = GetGameTime(npc.index) + 0.1; + + if(npc.m_flGetClosestTargetTime < GetGameTime(npc.index)) + { + npc.m_iTarget = GetClosestTarget(npc.index); + npc.m_flGetClosestTargetTime = GetGameTime(npc.index) + GetRandomRetargetTime(); + } + + if(IsValidEnemy(npc.index, npc.m_iTarget)) + { + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + if(flDistanceToTarget < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + } + if(npc.m_iChanged_WalkCycle == 1 && npc.Anger == false) + { + Victorian_ProtectorBuildObject(npc, flDistanceToTarget); + } + else + { + Victorian_ProtectorSelfDefense(npc,GetGameTime(npc.index), npc.m_iTarget, flDistanceToTarget); + } + } + else + { + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleAlertSound(); +} + +public Action Victorian_Protector_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + Victorian_Protector npc = view_as(victim); + + if(attacker <= 0) + return Plugin_Continue; + + if(npc.m_flArmorCount <= 0.0 && npc.Anger == false) + { + npc.Anger = true; + npc.m_iChanged_WalkCycle = 2; + npc.SetActivity("ACT_MP_RUN_MELEE"); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + npc.m_iWearable1 = npc.EquipItem("head", "models/workshop/weapons/c_models/C_Crossing_Guard/C_Crossing_Guard.mdl"); + SetVariantString("0.75"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + } + else + { + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + } + + return Plugin_Changed; +} + +public void Victorian_Protector_NPCDeath(int entity) +{ + Victorian_Protector npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + if(IsValidEntity(npc.m_iWearable7)) + RemoveEntity(npc.m_iWearable7); + if(IsValidEntity(npc.m_iWearable6)) + RemoveEntity(npc.m_iWearable6); + if(IsValidEntity(npc.m_iWearable5)) + RemoveEntity(npc.m_iWearable5); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); +} + +void Victorian_ProtectorBuildObject(Victorian_Protector npc, float distance) +{ + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 3.5)) + { + int Enemy_I_See = Can_I_See_Enemy(npc.index, npc.m_iTarget); + + if(IsValidEnemy(npc.index, Enemy_I_See)) + { + npc.m_iChanged_WalkCycle = 2; + npc.SetActivity("ACT_MP_RUN_MELEE"); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + + float pos[3]; GetEntPropVector(npc.index, Prop_Data, "m_vecAbsOrigin", pos); + float ang[3]; GetEntPropVector(npc.index, Prop_Data, "m_angRotation", ang); + npc.m_iWearable1 = npc.EquipItem("head", "models/workshop/weapons/c_models/C_Crossing_Guard/C_Crossing_Guard.mdl"); + SetVariantString("0.75"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + SetEntProp(npc.m_iWearable1, Prop_Send, "m_nSkin", 1); + float timeup = 5.0; + if(NpcStats_VictorianCallToArms(npc.index)) + timeup *= 2.0; + npc.m_iWearable7 = npc.SpawnShield(timeup, "models/props_mvm/mvm_player_shield.mdl",40.0, false); + SetEntProp(npc.m_iWearable7, Prop_Send, "m_nSkin", 1); + npc.PlayBuildSound(); + npc.m_flSpeed = 300.0; + npc.m_flArmorCount = 0.0; + } + } +} +void Victorian_ProtectorSelfDefense(Victorian_Protector npc, float gameTime, int target, float distance) +{ + if(npc.m_flAttackHappens) + { + if(npc.m_flAttackHappens < gameTime) + { + npc.m_flAttackHappens = 0.0; + + Handle swingTrace; + float VecEnemy[3]; WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 15000.0); + if(npc.DoSwingTrace(swingTrace, npc.m_iTarget)) + { + + target = TR_GetEntityIndex(swingTrace); + + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + + if(IsValidEnemy(npc.index, target)) + { + float damageDealt = 50.0; + + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 1.5; + + int DamageType = DMG_CLUB; + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DamageType, -1, _, vecHit); + + // Hit sound + npc.PlayMeleeHitSound(); + } + } + delete swingTrace; + } + } + + if(gameTime > npc.m_flNextMeleeAttack) + { + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED)) + { + int Enemy_I_See; + + Enemy_I_See = Can_I_See_Enemy(npc.index, npc.m_iTarget); + + if(IsValidEnemy(npc.index, Enemy_I_See)) + { + npc.m_iTarget = Enemy_I_See; + npc.PlayMeleeSound(); + npc.AddGesture("ACT_MP_ATTACK_STAND_MELEE",_,_,_,1.0); + + npc.m_flAttackHappens = gameTime + 0.25; + npc.m_flDoingAnimation = gameTime + 0.25; + npc.m_flNextMeleeAttack = gameTime + 1.0; + } + } + } +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_zapmarker.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_zapmarker.sp new file mode 100644 index 0000000000..ebed9f1989 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_zapmarker.sp @@ -0,0 +1,395 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + "vo/heavy_negativevocalization01.mp3", + "vo/heavy_negativevocalization02.mp3", + "vo/heavy_negativevocalization03.mp3" +}; + +static const char g_HurtSounds[][] = { + "vo/heavy_domination09.mp3", +}; + +static const char g_IdleAlertedSounds[][] = { + "vo/heavy_domination01.mp3", + "vo/heavy_domination02.mp3", + "vo/heavy_domination03.mp3", + "vo/heavy_domination04.mp3", + "vo/heavy_domination05.mp3", + "vo/heavy_domination06.mp3", + "vo/heavy_domination07.mp3", + "vo/heavy_domination08.mp3", +}; + +static const char g_MeleeAttackSounds[][] = { + "vo/heavy_meleeing01.mp3", + "vo/heavy_meleeing02.mp3", + "vo/heavy_meleeing03.mp3", + "vo/heavy_meleeing04.mp3", + "vo/heavy_meleeing05.mp3", + "vo/heavy_meleeing06.mp3", + "vo/heavy_meleeing07.mp3", + "vo/heavy_meleeing08.mp3", +}; + + +static const char g_MeleeHitSounds[][] = { + "weapons/cbar_hitbod1.wav", + "weapons/cbar_hitbod2.wav", + "weapons/cbar_hitbod3.wav", +}; + +static const char g_RangedAttackSounds[][] = { + "weapons/cleaver_throw.wav", +}; + +void Zapmarker_OnMapStart_NPC() +{ + for (int i = 0; i < (sizeof(g_DeathSounds)); i++) { PrecacheSound(g_DeathSounds[i]); } + for (int i = 0; i < (sizeof(g_HurtSounds)); i++) { PrecacheSound(g_HurtSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSound(g_IdleAlertedSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeAttackSounds)); i++) { PrecacheSound(g_MeleeAttackSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeHitSounds)); i++) { PrecacheSound(g_MeleeHitSounds[i]); } + + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Zapmarker"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_zapmarker"); + strcopy(data.Icon, sizeof(data.Icon), "victoria_zapper"); //leaderboard_class_(insert the name) + data.IconCustom = false; //download needed? + data.Flags = 0; //example: MVM_CLASS_FLAG_MINIBOSS|MVM_CLASS_FLAG_ALWAYSCRIT;, forces these flags. + data.Category = Type_Victoria; + data.Func = ClotSummon; + NPC_Add(data); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return Zapmaker(vecPos, vecAng, team); +} + +methodmap Zapmaker < CClotBody +{ + public void PlayIdleAlertSound() + { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(12.0, 24.0); + + } + + public void PlayHurtSound() + { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + + EmitSoundToAll(g_HurtSounds[GetRandomInt(0, sizeof(g_HurtSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + + } + + public void PlayDeathSound() + { + EmitSoundToAll(g_DeathSounds[GetRandomInt(0, sizeof(g_DeathSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + + public void PlayMeleeSound() + { + EmitSoundToAll(g_MeleeAttackSounds[GetRandomInt(0, sizeof(g_MeleeAttackSounds) - 1)], this.index, SNDCHAN_AUTO, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + public void PlayMeleeHitSound() + { + EmitSoundToAll(g_MeleeHitSounds[GetRandomInt(0, sizeof(g_MeleeHitSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + + } + public void PlayRangedSound() + { + EmitSoundToAll(g_RangedAttackSounds[GetRandomInt(0, sizeof(g_RangedAttackSounds) - 1)], this.index, SNDCHAN_AUTO, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + } + + public Zapmaker(float vecPos[3], float vecAng[3], int ally) + { + Zapmaker npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "5000", ally)); + + i_NpcWeight[npc.index] = 1; + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_MP_RUN_MELEE_ALLCLASS"); + if(iActivity > 0) npc.StartActivity(iActivity); + + SetVariantInt(4); + AcceptEntityInput(npc.index, "SetBodyGroup"); + + + + npc.m_flNextMeleeAttack = 0.0; + npc.m_flNextRangedAttack = 0.0; + npc.m_flNextRangedAttackHappening = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + func_NPCDeath[npc.index] = view_as(Internal_NPCDeath); + func_NPCOnTakeDamage[npc.index] = view_as(Internal_OnTakeDamage); + func_NPCThink[npc.index] = view_as(Internal_ClotThink); + + + npc.StartPathing(); + npc.m_flSpeed = 200.0; + + int skin = 1; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable1 = npc.EquipItem("head", "models/weapons/c_models/c_drg_thirddegree/c_drg_thirddegree.mdl"); + + npc.m_iWearable2 = npc.EquipItem("head", "models/workshop/player/items/all_class/dec15_patriot_peak/dec15_patriot_peak_heavy.mdl"); + + npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/player/items/heavy/fall17_siberian_tigerstripe/fall17_siberian_tigerstripe.mdl"); + + npc.m_iWearable4 = npc.EquipItem("head", "models/workshop/player/items/heavy/dec24_battle_balaclava_style1/dec24_battle_balaclava_style1.mdl"); + + npc.m_iWearable5 = npc.EquipItem("head", "models/workshop/player/items/heavy/sf14_heavy_robo_chest/sf14_heavy_robo_chest.mdl"); + + npc.m_iWearable6 = npc.EquipItem("head", "models/workshop/player/items/all_class/dec25_lazer_gazers/dec25_lazer_gazers_heavy.mdl"); + + SetVariantString("0.75"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + SetEntProp(npc.m_iWearable1, Prop_Send, "m_nSkin", 1); + SetEntityRenderColor(npc.m_iWearable1, 50, 80, 0, 255); + SetEntProp(npc.m_iWearable2, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable4, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable5, Prop_Send, "m_nSkin", skin); + SetEntProp(npc.m_iWearable6, Prop_Send, "m_nSkin", skin); + + return npc; + } +} + +static void Internal_ClotThink(int iNPC) +{ + Zapmaker npc = view_as(iNPC); + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + npc.Update(); + + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + if(npc.m_flNextThinkTime > GetGameTime(npc.index)) + { + return; + } + npc.m_flNextThinkTime = GetGameTime(npc.index) + 0.1; + + if(npc.m_flGetClosestTargetTime < GetGameTime(npc.index)) + { + npc.m_iTarget = GetClosestTarget(npc.index); + npc.m_flGetClosestTargetTime = GetGameTime(npc.index) + GetRandomRetargetTime(); + } + + if(IsValidEnemy(npc.index, npc.m_iTarget)) + { + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + if(flDistanceToTarget < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + } + ZapmakerSelfDefense(npc,GetGameTime(npc.index), npc.m_iTarget, flDistanceToTarget); + } + else + { + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleAlertSound(); +} + +static void Internal_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + Zapmaker npc = view_as(victim); + + if(attacker <= 0) + return; + + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } +} + +static void Internal_NPCDeath(int entity) +{ + Zapmaker npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + if(IsValidEntity(npc.m_iWearable6)) + RemoveEntity(npc.m_iWearable6); + if(IsValidEntity(npc.m_iWearable5)) + RemoveEntity(npc.m_iWearable5); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + +} + +void ZapmakerSelfDefense(Zapmaker npc, float gameTime, int target, float distance) +{ + if(!npc.m_flNextRangedAttackHappening) + { + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 12.0)) + { + int Enemy_I_See; + + Enemy_I_See = Can_I_See_Enemy(npc.index, npc.m_iTarget); + + if(IsValidEnemy(npc.index, Enemy_I_See)) + { + npc.m_flNextRangedAttack = gameTime + 0.25; + npc.m_flNextRangedAttackHappening = 1.0; + npc.AddGesture("ACT_MP_ATTACK_STAND_MELEE_ALLCLASS"); + npc.m_flDoingAnimation = gameTime + 0.25; + npc.m_flNextMeleeAttack = gameTime + 1.2; + } + } + return; + } + if(npc.m_flNextRangedAttack && npc.m_flNextRangedAttack != 5.0) + { + if(npc.m_flNextRangedAttack < gameTime) + { + float EnemyPos[3]; + WorldSpaceCenter(npc.m_iTarget, EnemyPos); + npc.FaceTowards(EnemyPos, 15000.0); + int projectile = npc.FireArrow(EnemyPos, 250.0, 1200.0, "models/weapons/c_models/c_drg_thirddegree/c_drg_thirddegree.mdl", 0.75); + WandProjectile_ApplyFunctionToEntity(projectile, Zapmarker_Axe_StartTouch); + + if(IsValidEntity(npc.m_iWearable1)) + { + RemoveEntity(npc.m_iWearable1); + } + npc.m_flNextRangedAttack = 5.0; + npc.PlayRangedSound(); + npc.m_flDoingAnimation = gameTime + 0.25; + } + } + if(npc.m_flNextRangedAttack && npc.m_flNextRangedAttack == 5.0) + { + npc.m_flNextRangedAttack = 0.0; + npc.m_iWearable1 = npc.EquipItem("head", "models/weapons/c_models/c_eviction_notice/c_eviction_notice.mdl"); + npc.SetActivity("ACT_MP_RUN_MELEE"); + npc.m_flSpeed = 275.0; + return; + } + + if(npc.m_flAttackHappens) + { + if(npc.m_flAttackHappens < gameTime) + { + npc.m_flAttackHappens = 0.0; + + Handle swingTrace; + float VecEnemy[3]; WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 15000.0); + if(npc.DoSwingTrace(swingTrace, npc.m_iTarget)) + { + + target = TR_GetEntityIndex(swingTrace); + + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + + if(IsValidEnemy(npc.index, target)) + { + float damageDealt = 35.0; + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 2.5; + + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_CLUB, -1, _, vecHit); + if(NpcStats_VictorianCallToArms(npc.index)) + Elemental_AddNervousDamage(target, npc.index, 5); + StartBleedingTimer(target, npc.index, 3.0, 2, -1, DMG_TRUEDAMAGE, 0); + + // Hit sound + npc.PlayMeleeHitSound(); + } + } + delete swingTrace; + } + } + + if(gameTime > npc.m_flNextMeleeAttack) + { + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED)) + { + int Enemy_I_See; + + Enemy_I_See = Can_I_See_Enemy(npc.index, npc.m_iTarget); + + if(IsValidEnemy(npc.index, Enemy_I_See)) + { + npc.m_iTarget = Enemy_I_See; + npc.PlayMeleeSound(); + npc.AddGesture("ACT_MP_ATTACK_STAND_MELEE"); + + npc.m_flAttackHappens = gameTime + 0.1; + npc.m_flDoingAnimation = gameTime + 0.1; + npc.m_flNextMeleeAttack = gameTime + 0.15; + } + } + } +} + +public void Zapmarker_Axe_StartTouch(int entity, int target) +{ + if(target > 0 && target < MAXENTITIES) //did we hit something??? + { + int owner = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity"); + if(!IsValidEntity(owner)) + { + owner = 0; + } + + int inflictor = h_ArrowInflictorRef[entity]; + if(inflictor != -1) + inflictor = EntRefToEntIndex(h_ArrowInflictorRef[entity]); + + if(inflictor == -1) + inflictor = owner; + + + EmitSoundToAll("weapons/3rd_degree_hit_01.wav", entity, _, 80, _, 0.8, 100); + if(IsValidEnemy(owner, target)) + ApplyStatusEffect(owner, target, "Teslar Electricution", NpcStats_VictorianCallToArms(owner) ? 7.5 : 5.0); + } + RemoveEntity(entity); +} \ No newline at end of file diff --git a/addons/sourcemod/translations/zombieriot.phrases.item.gift.desc.txt b/addons/sourcemod/translations/zombieriot.phrases.item.gift.desc.txt index ee8ccf74e8..b52d6e767a 100644 --- a/addons/sourcemod/translations/zombieriot.phrases.item.gift.desc.txt +++ b/addons/sourcemod/translations/zombieriot.phrases.item.gift.desc.txt @@ -3562,7 +3562,42 @@ { "en" " `Did you really thought you could get out this mess that easily?` \nColonel of Victoria's Army. He has mastered skill for explosives and command \nHe wants your death for the amends of Radiotower's destruction. Do we really have to fight him while we got same enemeis in common? \nHe will utilize all of the abilites that previous raidbosses used and often call in for support" } - + "Zapmarker Desc" + { + "en" "An elite melee unit of victoria \nThrows Zapper's axe to apply teslar debuff to its victim and rush in with melee that applies heavy bleed" + } + "Resource Collector Desc" + { + "en" "A robotic unit designed to collect nearby minerals \nFast and applied more damage to buildings" + } + "Victoria Gasleader Desc" + { + "en" "Victorian Chemical Platoon leader. \n applies armor corrosion elemental damage near while his armor is up \nPulls out a sword that applies more armor corrosion damage on 3rd hit when its target gets close \nBecomes stronger as near allies die" + } + "Demolitionist Desc" + { + "en" "Heavy melee unit of Victorian Chemical Platoon \nSwings a massive hammer to create and explosion that deals MASSIVE damage to buildings" + } + "Victorian Protector Desc" + { + "en" "Carrier unit holding a portable shield \n spawns with an armor and when it gets closer to its target, deployys an energy shield \nIt's shield carrier will be destroyed if its armor runs out" + } + "Airraider Desc" + { + "en" "A surprise assault unit of Victorian Chemical Platoon. \nParachutes in when it spawns and fire its rocket while falling down. \n continues with shotgun when on the ground" + } + "Victorian Headhunter Desc" + { + "en" "An elite sniper of Victorian Chemical Platoon. \n Appears quietly and deals armor corrsion damage \n Deals more damage and elemental damage to enemies with support weapon out" + } + "Chemical Specialist Desc" + { + "en" "A Chemical expert of Victorian Chemical Platoon \n Always head all of its elemental damage taken \n fire bullets coated with armor corrosion liquid" + } + "Giant Armored Medibot Desc" + { + "en" "A Giant support unit of Victorian Chemical Platoon designed only for defense \n its patient receives massive buff and never dies unless oneshot \nIt moves very slowly" + } "Avangard's Processing Core-B" { "en" "Avangard's Processing Core-B" diff --git a/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt b/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt index 5af59ea6b0..6d1a561831 100644 --- a/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt +++ b/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt @@ -783,6 +783,16 @@ "en" "Ammo Visualization" "ko" "탄약 시각화" } + "Buffweiser" + { + "en" "Buffweiser" + "ko" "버프와이저" + } + "Buffweiser Desc" + { + "en" "Boosts damage dealt by 100%\nReduces damage taken by 50%" + "ko" "공격 피해량이 100% 증가합니다.\n받는 피해량이 50% 감소합니다." + } "False Therapy" { "en" "False Therapy" diff --git a/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt b/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt index 07c8c4b092..79d8f2aef5 100644 --- a/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt +++ b/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt @@ -5868,6 +5868,42 @@ "en" "Captino Menius" "ko" "캡티노 메니우스" } + "Zapmarker" + { + "en" "Zapmarker" + } + "Resource Collector" + { + "en" "Resource Collector" + } + "Victoria Gasleader" + { + "en" "Victorian Chemical Squad Leader" + } + "Demolitionist" + { + "en" "Demolitionist" + } + "Victorian Protector" + { + "en" "Victorian Protector" + } + "Airraider" + { + "en" "Airraider" + } + "Victorian Headhunter" + { + "en" "Victorian Headhunter" + } + "Chemical Specialist" + { + "en" "Chemical Specialist" + } + "Giant Armored Medibot" + { + "en" "Giant Armored Medibot" + } "0h No it's Not Fair" { "en" "=Failed name=" From 866694356d3ae82ad2111efb0b3226ef5cb3b758 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Sat, 7 Feb 2026 23:12:43 +0100 Subject: [PATCH 02/24] save --- .../configs/zombie_riot/construction/ending1_final.cfg | 2 -- .../configs/zombie_riot/dungeon/final_expidonsa.cfg | 2 -- .../configs/zombie_riot/dungeon/final_space.cfg | 2 -- .../sourcemod/configs/zombie_riot/dungeon/raid_2_2.cfg | 1 + .../sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg | 1 + .../zombie_riot/maps/zr_const2_headquarters.cfg | 1 + .../construction/construction2/npc_starship_regalia.sp | 10 ++++++++++ .../zombie_riot/npc/construction/enemies/npc_zilius.sp | 10 ++++++++++ 8 files changed, 23 insertions(+), 6 deletions(-) diff --git a/addons/sourcemod/configs/zombie_riot/construction/ending1_final.cfg b/addons/sourcemod/configs/zombie_riot/construction/ending1_final.cfg index 7140b59e3b..a9740c5127 100644 --- a/addons/sourcemod/configs/zombie_riot/construction/ending1_final.cfg +++ b/addons/sourcemod/configs/zombie_riot/construction/ending1_final.cfg @@ -1,7 +1,5 @@ "Waves" { - "complete_item" "Foreign Expidonsan Chip" - "1" { "music_1" diff --git a/addons/sourcemod/configs/zombie_riot/dungeon/final_expidonsa.cfg b/addons/sourcemod/configs/zombie_riot/dungeon/final_expidonsa.cfg index cc37dca45e..63c5b98cae 100644 --- a/addons/sourcemod/configs/zombie_riot/dungeon/final_expidonsa.cfg +++ b/addons/sourcemod/configs/zombie_riot/dungeon/final_expidonsa.cfg @@ -1,7 +1,5 @@ "Waves" { - "complete_item" "Foreign Expidonsan Chip" - "1" { "0.11" diff --git a/addons/sourcemod/configs/zombie_riot/dungeon/final_space.cfg b/addons/sourcemod/configs/zombie_riot/dungeon/final_space.cfg index 9f9745dee0..4fa31e4699 100644 --- a/addons/sourcemod/configs/zombie_riot/dungeon/final_space.cfg +++ b/addons/sourcemod/configs/zombie_riot/dungeon/final_space.cfg @@ -1,7 +1,5 @@ "Waves" { - "complete_item" "Almagest Data Card" - "1" { diff --git a/addons/sourcemod/configs/zombie_riot/dungeon/raid_2_2.cfg b/addons/sourcemod/configs/zombie_riot/dungeon/raid_2_2.cfg index 1be932fe54..bfff738bc2 100644 --- a/addons/sourcemod/configs/zombie_riot/dungeon/raid_2_2.cfg +++ b/addons/sourcemod/configs/zombie_riot/dungeon/raid_2_2.cfg @@ -15,6 +15,7 @@ "2" { "give_rogue_artifact" "Xeno Resurgance" + "music_1" { "file" "#zombiesurvival/dungeon/raid_attack_2.mp3" diff --git a/addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg b/addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg index b8777687e0..59bcea07fb 100644 --- a/addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg +++ b/addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg @@ -15,6 +15,7 @@ "name" "Stealth Blades" "author" "Galaxy On Fire 2" } + "1.5" { "count" "3" diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_const2_headquarters.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_const2_headquarters.cfg index 862a164f90..c5f7b4d453 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_const2_headquarters.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_const2_headquarters.cfg @@ -74,6 +74,7 @@ "dungeon/raid_3_1" "" "dungeon/raid_3_2" "" "dungeon/raid_3_3" "" + "dungeon/raid_3_$" "" } "4" { diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_regalia.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_regalia.sp index 19dc4039ca..184723be08 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_regalia.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_regalia.sp @@ -3742,6 +3742,16 @@ static void NPC_Death(int iNPC) { Waves_ClearWaves(); ForcePlayerWin(); + for (int client = 1; client <= MaxClients; client++) + { + if(IsValidClient(client) && GetClientTeam(client) == 2 && TeutonType[client] != TEUTON_WAITING && PlayerPoints[client] > 500) + { + if(Items_GiveNamedItem(client, "Almagest Data Card")) + { + CPrintToChat(client, "{green}Obtained{yellow} ''Almagest Data Card''"); + } + } + } for(int i; i < i_MaxcountNpcTotal; i++) { int entitynpc = EntRefToEntIndexFast(i_ObjectsNpcsTotal[i]); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/enemies/npc_zilius.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/enemies/npc_zilius.sp index 18a5e89d14..5e27e6997f 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/construction/enemies/npc_zilius.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/enemies/npc_zilius.sp @@ -639,6 +639,16 @@ static void Internal_ClotThink(int iNPC) } default: { + for (int client = 1; client <= MaxClients; client++) + { + if(IsValidClient(client) && GetClientTeam(client) == 2 && TeutonType[client] != TEUTON_WAITING && PlayerPoints[client] > 500) + { + if(Items_GiveNamedItem(client, "Foreign Expidonsan Chip")) + { + CPrintToChat(client, "{green}Obtained{yellow} ''Foreign Expidonsan Chip''"); + } + } + } ForcePlayerWin(); npc.m_flWinAnimationSay = 0.0; npc.m_flWinAnimation = 0.0; From bba51a32f03ea4a54895e1d10abb23867bada7f6 Mon Sep 17 00:00:00 2001 From: BeeepG <154726445+BeeepG@users.noreply.github.com> Date: Sun, 8 Feb 2026 18:42:29 +0900 Subject: [PATCH 03/24] Changesforconstruiction (#1221) * Update zombieriot.phrases.status_effects.txt * adds --- .../base_spawners/difficulty_4/variant_1.cfg | 24 +++++++--- .../base_spawners/difficulty_4/variant_2.cfg | 9 +++- .../base_spawners/difficulty_4/variant_3.cfg | 44 ++++++++++--------- .../configs/zombie_riot/dungeon/raid_3_4.cfg | 22 +++++----- .../zombieriot.phrases.status_effects.txt | 4 +- 5 files changed, 63 insertions(+), 40 deletions(-) diff --git a/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_1.cfg b/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_1.cfg index 68a4ded027..1ca886d497 100644 --- a/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_1.cfg +++ b/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_1.cfg @@ -4,24 +4,38 @@ { "1.0" { - "count" "4" + "count" "2" "health" "30000" "extra_damage" "1.5" - "plugin" "npc_mechafist" + "plugin" "npc_protector" } "1.0" { - "count" "4" + "count" "2" + "health" "30000" + "extra_damage" "1.0" + "plugin" "npc_airraider" + } + "1.0" + { + "count" "2" + "health" "30000" + "extra_damage" "1.5" + "plugin" "npc_zapmarker" + } + "1.0" + { + "count" "2" "health" "50000" "extra_damage" "1.5" - "plugin" "npc_blocker" + "plugin" "npc_chemical_specialist" } "1.0" { "count" "2" "health" "90000" "extra_damage" "1.5" - "plugin" "npc_payback" + "plugin" "npc_demolitionist" } } "Freeplay" diff --git a/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_2.cfg b/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_2.cfg index e4836e431c..618463079f 100644 --- a/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_2.cfg +++ b/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_2.cfg @@ -18,11 +18,18 @@ } "1.0" { - "count" "4" + "count" "2" "health" "30000" "extra_damage" "1.0" "plugin" "npc_scorcher" } + "1.0" + { + "count" "2" + "health" "30000" + "extra_damage" "1.0" + "plugin" "npc_resource_collector" + } } "Freeplay" { diff --git a/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_3.cfg b/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_3.cfg index 171715bd17..35bdd0d175 100644 --- a/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_3.cfg +++ b/addons/sourcemod/configs/zombie_riot/dungeon/base_spawners/difficulty_4/variant_3.cfg @@ -7,21 +7,21 @@ "count" "4" "health" "30000" "extra_damage" "1.5" - "plugin" "npc_mechafist" + "plugin" "npc_resource_collector" } "1.0" { "count" "4" - "health" "50000" - "extra_damage" "1.5" - "plugin" "npc_blocker" + "health" "40000" + "extra_damage" "1.0" + "plugin" "npc_airraider" } "1.0" { - "count" "2" - "health" "90000" + "count" "1" + "health" "100000" "extra_damage" "1.5" - "plugin" "npc_payback" + "plugin" "npc_giant_armored_medic" } "1.0" { @@ -42,28 +42,29 @@ "count" "4" "health" "30000" "extra_damage" "1.0" - "plugin" "npc_scorcher" + "plugin" "npc_zapmarker" } "1.0" { "count" "4" "health" "30000" "extra_damage" "1.5" - "plugin" "npc_mechafist" + "plugin" "npc_resource_collector" + } "1.0" { "count" "4" "health" "50000" "extra_damage" "1.5" - "plugin" "npc_blocker" + "plugin" "npc_zapmarker" } "1.0" { "count" "2" "health" "90000" "extra_damage" "1.5" - "plugin" "npc_payback" + "plugin" "npc_demolitionist" } "1.0" { @@ -84,14 +85,14 @@ "count" "4" "health" "30000" "extra_damage" "1.0" - "plugin" "npc_scorcher" + "plugin" "npc_protector" } "1.0" { - "count" "4" - "health" "30000" - "extra_damage" "1.5" - "plugin" "npc_mechafist" + "count" "2" + "health" "20000" + "extra_damage" "1.0" + "plugin" "npc_headhunter" } "1.0" { @@ -104,16 +105,17 @@ "1.0" { "count" "4" - "health" "50000" + "health" "124000" "extra_damage" "1.5" - "plugin" "npc_blocker" + "plugin" "npc_demolitionist" } "1.0" { "count" "2" "health" "90000" "extra_damage" "1.5" - "plugin" "npc_payback" + "data" "only" + "plugin" "npc_avangard" } "1.0" { @@ -127,14 +129,14 @@ "count" "2" "health" "120000" "extra_damage" "1.25" - "plugin" "npc_mowdown" + "plugin" "npc_giant_armored_medic" } "1.0" { "count" "4" "health" "30000" "extra_damage" "1.0" - "plugin" "npc_scorcher" + "plugin" "npc_protector" } } "Freeplay" diff --git a/addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg b/addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg index 59bcea07fb..226017aa7a 100644 --- a/addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg +++ b/addons/sourcemod/configs/zombie_riot/dungeon/raid_3_4.cfg @@ -158,9 +158,9 @@ "1.5" { "count" "4" - "health" "50000" - "extra_damage" "2.0" - "plugin" "npc_contracted_motivator" + "health" "55000" + "extra_damage" "4.0" + "plugin" "npc_antiarmor_infantry" "spawn" "home_attackerspawn" } "1.5" @@ -174,10 +174,10 @@ "1.5" { "count" "3" - "health" "70000" + "health" "40000" "extra_damage" "1.5" - "extra_speed" "0.75" - "plugin" "npc_zombie_engineer_grave" + "extra_speed" "1.15" + "plugin" "npc_tanker" "spawn" "home_attackerspawn" } "1.5" @@ -296,9 +296,9 @@ "1.5" { "count" "3" - "health" "15000" - "extra_damage" "1.0" - "plugin" "npc_chaos_gunmen" + "health" "50000" + "extra_damage" "4.0" + "plugin" "npc_supplier" "spawn" "home_attackerspawn" } "1.5" @@ -417,8 +417,8 @@ { "count" "4" "health" "50000" - "extra_damage" "2.0" - "plugin" "npc_contracted_motivator" + "extra_damage" "4.0" + "plugin" "npc_supplier" "spawn" "home_attackerspawn" } "1.5" diff --git a/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt b/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt index 6d1a561831..e5bfe54b25 100644 --- a/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt +++ b/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt @@ -790,8 +790,8 @@ } "Buffweiser Desc" { - "en" "Boosts damage dealt by 100%\nReduces damage taken by 50%" - "ko" "공격 피해량이 100% 증가합니다.\n받는 피해량이 50% 감소합니다." + "en" "Boosts damage dealt by 100%\nReduces damage taken by 50%" + "ko" "공격 피해량이 100% 증가합니다.\n받는 피해량이 50% 감소합니다." } "False Therapy" { From 949f2e810dd4366700fdc7c97563fde06969684a Mon Sep 17 00:00:00 2001 From: Supergamer120 Date: Sun, 8 Feb 2026 04:43:24 -0500 Subject: [PATCH 04/24] New vic con 2 enemies in freeplay (#1222) * Update configuration for zombie riot construction * Update NPC settings in 6_2.cfg Added new NPC configuration for factory emergency extraction. * Add emergency extraction configuration for NPCs * Update 4_1.cfg to include retreat NPC settings Added configuration for retreating all factory NPCs. * Add NPC configurations for advanced challenges Added new NPC configurations with various attributes including count, health, extra damage, and danger level. --- .../challenges/freeplay/advanced.cfg | 73 +++++++++++++++++++ .../configs/zombie_riot/construction/3_2.cfg | 8 ++ .../configs/zombie_riot/construction/4_1.cfg | 8 ++ .../configs/zombie_riot/construction/6_2.cfg | 8 ++ .../configs/zombie_riot/construction/9_7.cfg | 8 ++ 5 files changed, 105 insertions(+) diff --git a/addons/sourcemod/configs/zombie_riot/challenges/freeplay/advanced.cfg b/addons/sourcemod/configs/zombie_riot/challenges/freeplay/advanced.cfg index 62ea1e3c48..ca2e58ff63 100644 --- a/addons/sourcemod/configs/zombie_riot/challenges/freeplay/advanced.cfg +++ b/addons/sourcemod/configs/zombie_riot/challenges/freeplay/advanced.cfg @@ -4111,6 +4111,70 @@ "plugin" "npc_skilled_crossbowman" "danger_level" "5" } + "2.5" + { + "count" "10" + "health" "100000" + "extra_damage" "1.26" + "plugin" "npc_airraider" + "danger_level" "5" + } + "2.5" + { + "count" "10" + "health" "100000" + "extra_damage" "1.26" + "plugin" "npc_resource_collector" + "danger_level" "5" + } + "2.5" + { + "count" "10" + "health" "100000" + "extra_damage" "1.26" + "plugin" "npc_chemical_spreader" + "danger_level" "5" + } + "2.5" + { + "count" "10" + "health" "100000" + "extra_damage" "1.26" + "plugin" "npc_chemical_specialist" + "danger_level" "5" + } + "2.5" + { + "count" "10" + "health" "300000" + "extra_damage" "1.26" + "plugin" "npc_demolitionist" + "danger_level" "5" + } + "2.5" + { + "count" "10" + "health" "150000" + "extra_damage" "1.26" + "plugin" "npc_giant_armored_medic" + "danger_level" "1" + } + "2.5" + { + "count" "10" + "health" "100000" + "extra_damage" "1.26" + "plugin" "npc_protector" + "danger_level" "5" + } + "2.5" + { + "count" "10" + "health" "100000" + "extra_damage" "1.26" + "plugin" "npc_headhunter" + "danger_level" "5" + } //bosses "2.5" @@ -4123,6 +4187,15 @@ "is_boss" "1" } "2.5" + { + "count" "0" + "health" "3500000" + "plugin" "npc_gasleader" + "extra_damage" "1.26" + "danger_level" "4" + "is_boss" "1" + } + "2.5" { "count" "0" "health" "3500000" diff --git a/addons/sourcemod/configs/zombie_riot/construction/3_2.cfg b/addons/sourcemod/configs/zombie_riot/construction/3_2.cfg index 7f260bfec9..3a2dcd9c08 100644 --- a/addons/sourcemod/configs/zombie_riot/construction/3_2.cfg +++ b/addons/sourcemod/configs/zombie_riot/construction/3_2.cfg @@ -50,6 +50,14 @@ "count" "2" "plugin" "npc_payback" } + "0.01" + { + //Retreat All Factory + "count" "0" + "health" "19721121" + "data" "factory_emergency_extraction" + "plugin" "npc_invisible_trigger" + } } "Freeplay" { diff --git a/addons/sourcemod/configs/zombie_riot/construction/4_1.cfg b/addons/sourcemod/configs/zombie_riot/construction/4_1.cfg index 0c4a136034..3d494a7426 100644 --- a/addons/sourcemod/configs/zombie_riot/construction/4_1.cfg +++ b/addons/sourcemod/configs/zombie_riot/construction/4_1.cfg @@ -60,6 +60,14 @@ "count" "10" "plugin" "npc_blocker" } + "0.01" + { + //Retreat All Factory + "count" "0" + "health" "19721121" + "data" "factory_emergency_extraction" + "plugin" "npc_invisible_trigger" + } } "Freeplay" { diff --git a/addons/sourcemod/configs/zombie_riot/construction/6_2.cfg b/addons/sourcemod/configs/zombie_riot/construction/6_2.cfg index 086b23cc7a..a4daed9758 100644 --- a/addons/sourcemod/configs/zombie_riot/construction/6_2.cfg +++ b/addons/sourcemod/configs/zombie_riot/construction/6_2.cfg @@ -80,6 +80,14 @@ "health" "60000" "plugin" "npc_assaulter" } + "0.01" + { + //Retreat All Factory + "count" "0" + "health" "19721121" + "data" "factory_emergency_extraction" + "plugin" "npc_invisible_trigger" + } } "Freeplay" { diff --git a/addons/sourcemod/configs/zombie_riot/construction/9_7.cfg b/addons/sourcemod/configs/zombie_riot/construction/9_7.cfg index 1e9fb3bb64..4ed6c480c1 100644 --- a/addons/sourcemod/configs/zombie_riot/construction/9_7.cfg +++ b/addons/sourcemod/configs/zombie_riot/construction/9_7.cfg @@ -39,6 +39,14 @@ "health" "200000" "plugin" "npc_medival_monk" } + "0.01" + { + //Retreat All Factory + "count" "0" + "health" "19721121" + "data" "factory_emergency_extraction" + "plugin" "npc_invisible_trigger" + } } "Freeplay" { From f6f1fc9d7b44236ebd277c39b06bbba04a96be0a Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Sun, 8 Feb 2026 10:44:15 +0100 Subject: [PATCH 05/24] fix --- .../configs/zombie_riot/maps/zr_const2_headquarters.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_const2_headquarters.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_const2_headquarters.cfg index c5f7b4d453..5f612b9d59 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_const2_headquarters.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_const2_headquarters.cfg @@ -74,7 +74,7 @@ "dungeon/raid_3_1" "" "dungeon/raid_3_2" "" "dungeon/raid_3_3" "" - "dungeon/raid_3_$" "" + "dungeon/raid_3_4" "" } "4" { From f01ace6e0bca72151353cd054335029101292fe9 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Sun, 8 Feb 2026 10:54:04 +0100 Subject: [PATCH 06/24] save --- .../sourcemod/scripting/zombie_riot/dungeons.sp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/addons/sourcemod/scripting/zombie_riot/dungeons.sp b/addons/sourcemod/scripting/zombie_riot/dungeons.sp index 467a465527..945aacd7b9 100644 --- a/addons/sourcemod/scripting/zombie_riot/dungeons.sp +++ b/addons/sourcemod/scripting/zombie_riot/dungeons.sp @@ -1985,7 +1985,18 @@ static void StartBattle(const RoomInfo room, float time = 0.1) snap.GetKey(length, buffer, sizeof(buffer)); room.Fights.GetValue(buffer, scale); - EnemyScaling = ScaleBasedOnRound(round) / ScaleBasedOnRound(scale); + //we will scale down round linearly + if(round >= 30) + { + //we lessen scaling number + round += 2; + } + else + { + //we up scaling + round -= 5; + } + EnemyScaling = ScaleBasedOnRound((round - 6)) / ScaleBasedOnRound(scale); PrintToConsoleAll("Dungeon Enemy Scaling: %.2f%%", EnemyScaling * 100.0); BuildPath(Path_SM, buffer, sizeof(buffer), CONFIG_CFG, buffer); @@ -2194,7 +2205,7 @@ bool Dungeon_AtLimitNotice() static float ScaleBasedOnRound(int round) { - return (500.0 + Pow(float(round), 2.7)); + return (1000.0 + Pow(float(round), 2.7)); } void Dungeon_EnemySpawned(int entity) From ef1165bd9e9d9a68c33cfc85c1d8bc2c738b654d Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Sun, 8 Feb 2026 10:54:39 +0100 Subject: [PATCH 07/24] Update dungeons.sp --- addons/sourcemod/scripting/zombie_riot/dungeons.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/zombie_riot/dungeons.sp b/addons/sourcemod/scripting/zombie_riot/dungeons.sp index 945aacd7b9..7bac75e844 100644 --- a/addons/sourcemod/scripting/zombie_riot/dungeons.sp +++ b/addons/sourcemod/scripting/zombie_riot/dungeons.sp @@ -2236,7 +2236,7 @@ void Dungeon_EnemySpawned(int entity) if(EnemyScaling > 0.0) { - fl_Extra_Damage[entity] *= 1.0 + ((EnemyScaling - 1.0) / 3.0); + fl_Extra_Damage[entity] *= 1.0 + ((EnemyScaling - 1.0) / 4.0); SetEntProp(entity, Prop_Data, "m_iHealth", RoundToCeil(float(GetEntProp(entity, Prop_Data, "m_iHealth")) * EnemyScaling)); SetEntProp(entity, Prop_Data, "m_iMaxHealth", RoundToCeil(float(ReturnEntityMaxHealth(entity)) * EnemyScaling)); From 9f2aa24859db61590a9e38e163e4ea3fc5cabe40 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Sun, 8 Feb 2026 10:56:18 +0100 Subject: [PATCH 08/24] save --- addons/sourcemod/scripting/shared/status_effects.sp | 10 +++++----- .../translations/zombieriot.phrases.status_effects.txt | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/addons/sourcemod/scripting/shared/status_effects.sp b/addons/sourcemod/scripting/shared/status_effects.sp index 74545cec75..9faaaef86d 100644 --- a/addons/sourcemod/scripting/shared/status_effects.sp +++ b/addons/sourcemod/scripting/shared/status_effects.sp @@ -7353,10 +7353,10 @@ void StatusEffects_Construct2_EnemyModifs() strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Xeno"); //-1.0 means unused - data.DamageTakenMulti = 0.75; - data.DamageDealMulti = 0.3; + data.DamageTakenMulti = 0.65; + data.DamageDealMulti = 0.4; data.MovementspeedModif = -1.0; - data.AttackspeedBuff = (1.0 / 0.85); + data.AttackspeedBuff = (1.0 / 0.9); data.Positive = true; data.ShouldScaleWithPlayerCount = false; data.OnBuffStarted = Const2Modifs_Xeno_Start; @@ -7369,10 +7369,10 @@ void StatusEffects_Construct2_EnemyModifs() strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), ""); //-1.0 means unused - data.DamageTakenMulti = 0.7; + data.DamageTakenMulti = 0.65; data.DamageDealMulti = 0.4; data.MovementspeedModif = -1.0; - data.AttackspeedBuff = (1.0 / 0.85); + data.AttackspeedBuff = (1.0 / 0.9); data.Positive = true; data.ShouldScaleWithPlayerCount = false; data.OnBuffStarted = Const2Modifs_Xeno_Start_Already; diff --git a/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt b/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt index e5bfe54b25..30ebdc9776 100644 --- a/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt +++ b/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt @@ -2811,8 +2811,8 @@ } "Xeno Infection Desc" { - "en" "Npc Gains 25% Resistance, 30% Damage, but thinks 15% slower, and regens over time upto 1.35x max health, if above 25% max health, gain immensive buffs untill below\ninfects any enemy with xeno aswell." - "ko" "NPC 저항력 25%, 피해량 30% 증가. 생각 속도 15% 감소. 최대 체력의 1.35배까지 재생. 체력이 25% 이상이라면 그 이하가 될 때까지 강력한 버프 획득\n다른 적에게도 제노를 감염시킴" + "en" "Npc Gains 35% Resistance, 40% Damage, but thinks 10% slower, and regens over time upto 1.35x max health, if above 25% max health, gain immensive buffs untill below\ninfects any enemy with xeno aswell." + "ko" "NPC 저항력 35%, 피해량 40% 증가. 생각 속도 10% 감소. 최대 체력의 1.35배까지 재생. 체력이 25% 이상이라면 그 이하가 될 때까지 강력한 버프 획득\n다른 적에게도 제노를 감염시킴" } "Xeno" { From 5404d569ce1f85df14303c29fe90a0e5fb36dc20 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Sun, 8 Feb 2026 11:19:14 +0100 Subject: [PATCH 09/24] save --- .../sourcemod/scripting/zombie_riot/dungeons.sp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/addons/sourcemod/scripting/zombie_riot/dungeons.sp b/addons/sourcemod/scripting/zombie_riot/dungeons.sp index 7bac75e844..4cc27a5e70 100644 --- a/addons/sourcemod/scripting/zombie_riot/dungeons.sp +++ b/addons/sourcemod/scripting/zombie_riot/dungeons.sp @@ -1986,15 +1986,20 @@ static void StartBattle(const RoomInfo room, float time = 0.1) room.Fights.GetValue(buffer, scale); //we will scale down round linearly + if(round >= 25) + { + //we lessen scaling number + round += 1; + } if(round >= 30) { //we lessen scaling number - round += 2; + round += 1; } - else + if(round >= 40) { - //we up scaling - round -= 5; + //we lessen scaling number + round += 1; } EnemyScaling = ScaleBasedOnRound((round - 6)) / ScaleBasedOnRound(scale); PrintToConsoleAll("Dungeon Enemy Scaling: %.2f%%", EnemyScaling * 100.0); @@ -2205,7 +2210,7 @@ bool Dungeon_AtLimitNotice() static float ScaleBasedOnRound(int round) { - return (1000.0 + Pow(float(round), 2.7)); + return (750.0 + Pow(float(round), 2.8)); } void Dungeon_EnemySpawned(int entity) From d4f3a5b3ed883010b3d783e625923f0db85eb721 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Sun, 8 Feb 2026 12:16:39 +0100 Subject: [PATCH 10/24] save --- .../npc/construction/construction2/npc_chaos_bladethrower.sp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_chaos_bladethrower.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_chaos_bladethrower.sp index 2e00e29c60..90522b1932 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_chaos_bladethrower.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_chaos_bladethrower.sp @@ -322,9 +322,10 @@ public void ArrowStartTouchPierce(int arrow, int entity) return; Set_HitDetectionCooldown(arrow,entity, FAR_FUTURE); + float DamageGet = f_ArrowDamage[arrow]; if(ShouldNpcDealBonusDamage(entity)) { - f_ArrowDamage[arrow] *= 3.0; + DamageGet *= 3.0; } int owner = GetEntPropEnt(arrow, Prop_Send, "m_hOwnerEntity"); @@ -340,7 +341,7 @@ public void ArrowStartTouchPierce(int arrow, int entity) if(inflictor == -1) inflictor = owner; - SDKHooks_TakeDamage(entity, owner, inflictor, f_ArrowDamage[arrow], DMG_BULLET|DMG_PREVENT_PHYSICS_FORCE, -1); + SDKHooks_TakeDamage(entity, owner, inflictor, DamageGet, DMG_BULLET|DMG_PREVENT_PHYSICS_FORCE, -1); Projectile_DealElementalDamage(entity, arrow); EmitSoundToAll(g_ArrowHitSoundSuccess[GetRandomInt(0, sizeof(g_ArrowHitSoundSuccess) - 1)], arrow, _, 80, _, 0.8, 100); From 3739a00f71fedd0dc951adb6b83b723261baf4c8 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Sun, 8 Feb 2026 13:49:26 +0100 Subject: [PATCH 11/24] save --- .../npc/construction/construction2/npc_starship_beacon.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_beacon.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_beacon.sp index 363f21b4e3..1e9c2f1e58 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_beacon.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_beacon.sp @@ -282,7 +282,7 @@ static void HandleSummoning(Starship_Beacon npc) int health = ReturnEntityMaxHealth(npc.index); int SpwanIndex = NPC_CreateByName("npc_almagest_proxima", npc.index, Loc, {0.0, 0.0, 0.0}, GetTeam(npc.index)); - + health /= 4; if(SpwanIndex > MaxClients) { SetEntProp(SpwanIndex, Prop_Data, "m_iHealth", health); From 3b9693bce25484f644b36da10caea363748860fd Mon Sep 17 00:00:00 2001 From: jDeivid <106876411+jDaivid@users.noreply.github.com> Date: Sun, 8 Feb 2026 15:49:43 +0200 Subject: [PATCH 12/24] Various things (#1223) * wait until further response * teslar * reiuji spam nerf * the alt * test later * something is broke. figure it out/fix it later * thought * finish * Balance * text stuffs * how did that get in * Update zombieriot.phrases.weapons.txt * Update zombieriot.phrases.weapons.description.txt * nerf dmg of blitz kit melee * lower KB * minor spelling mistake * you're telling me a ginger, bread, this man? * test later * fix prismatic issue with skill points * thats a big flying bird * if it flies, we can probably shoot it down * IT CAN SHOOT BACK??? * we'll be fine solong as it doesn't have lasers- * kirov reporting * blend * do * tickrate and drone fix * "None can see me even if they try" * do --------- Co-authored-by: Artvin <76885107+artvin01@users.noreply.github.com> --- .../npc_lantean_drone_projectile.sp | 4 ++++ .../construction2/npc_starship_regalia.sp | 20 ++++++++++++++----- .../victorians/npc_chemical_specialist.sp | 4 ++-- .../construction2/victorians/npc_gasleader.sp | 2 +- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_lantean_drone_projectile.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_lantean_drone_projectile.sp index c4e4896e54..b8fa17311d 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_lantean_drone_projectile.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_lantean_drone_projectile.sp @@ -87,10 +87,12 @@ methodmap LanteanProjectile < CClotBody if(StrContains(data, "red") != -1) { npc.m_iWearable1 = ParticleEffectAt_Parent(Origin, "flaregun_energyfield_red", npc.index, "", {0.0,0.0,0.0}); + npc.m_iWearable2 = ParticleEffectAt_Parent(Origin, "raygun_projectile_red_trail", npc.index, "", {0.0,0.0,0.0}); } else if(StrContains(data, "blue") != -1) { npc.m_iWearable1 = ParticleEffectAt_Parent(Origin, "flaregun_energyfield_blue", npc.index, "", {0.0,0.0,0.0}); + npc.m_iWearable2 = ParticleEffectAt_Parent(Origin, "raygun_projectile_blue_trail", npc.index, "", {0.0,0.0,0.0}); } //is always static AddNpcToAliveList(npc.index, 1); @@ -450,6 +452,8 @@ static void LanteanNPC_Death(int iNPC) if(IsValidEntity(npc.m_iWearable1)) RemoveEntity(npc.m_iWearable1); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); SetEntityRenderMode(npc.index, RENDER_NORMAL); SetEntityRenderColor(npc.index, 255, 255, 255, 255); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_regalia.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_regalia.sp index 184723be08..2f95bda550 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_regalia.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/npc_starship_regalia.sp @@ -1328,7 +1328,7 @@ methodmap RegaliaClass < CClotBody for(int i=0 ; i < 2 ; i ++) { - int particle_1 = ParticleEffectAt({0.0,0.0,0.0}, skin == 1 ? "raygun_projectile_blue_crit" : "raygun_projectile_red_crit", 0.0); + int particle_1 = ParticleEffectAt({0.0,0.0,0.0}, skin == 1 ? "raygun_projectile_blue_trail" : "raygun_projectile_red_trail", 0.0); SetParent(this.index, particle_1, Sections[i]); this.AddAttachedEntity(particle_1); } @@ -1347,7 +1347,7 @@ methodmap RegaliaClass < CClotBody for(int i=0 ; i < 2 ; i ++) { - int particle_1 = ParticleEffectAt({0.0,0.0,0.0}, skin == 1 ? "raygun_projectile_blue_crit" : "raygun_projectile_red_crit", 0.0); + int particle_1 = ParticleEffectAt({0.0,0.0,0.0}, skin == 1 ? "raygun_projectile_blue_trail" : "raygun_projectile_red_trail", 0.0); SetParent(this.index, particle_1, Sections[i]); this.AddAttachedEntity(particle_1); } @@ -2963,6 +2963,11 @@ static void HandleDroneSystem(RegaliaClass npc) float ShipAngles[3]; ShipAngles = npc.GetAngles(); + int iTargetList[MAXPLAYERS]; + UnderTides npcGetInfo = view_as(npc.index); + GetHighDefTargets(npcGetInfo, iTargetList, sizeof(iTargetList), false, false); + int target_loop = 0; + if(TopSection) { for(int i=0 ; i < 2 ; i++) @@ -2974,7 +2979,8 @@ static void HandleDroneSystem(RegaliaClass npc) Angles[2] = 0.0; Angles[1] += (360.0 / SpawnAmt) * loop; Angles[0] = -45.0; - FireDrones(npc, Loc, Angles); + FireDrones(npc, Loc, Angles, iTargetList[target_loop]); + target_loop++; } } } @@ -2989,12 +2995,13 @@ static void HandleDroneSystem(RegaliaClass npc) Angles[2] = 0.0; Angles[1] += (360.0 / SpawnAmt) * loop; Angles[0] = 45.0; - FireDrones(npc, Loc, Angles); + FireDrones(npc, Loc, Angles, iTargetList[target_loop]); + target_loop++; } } } } -static void FireDrones(CClotBody npc, float Loc[3], float Angles[3]) +static void FireDrones(CClotBody npc, float Loc[3], float Angles[3], int target = -1) { int Drone = NPC_CreateByName("npc_lantean_drone_projectile", npc.index, Loc, Angles, GetTeam(npc.index), "blue;raidmodescaling_damage"); int health = RoundToFloor(ReturnEntityMaxHealth(npc.index) * 0.0005); //like 0.05% hp of ship @@ -3011,6 +3018,9 @@ static void FireDrones(CClotBody npc, float Loc[3], float Angles[3]) drone_npc.m_flTimeTillDeath = GetGameTime() + 10.0 + GetRandomFloat(0.5, 5.0); drone_npc.m_flSpeed = DroneSpeed + 600.0 * GetRandomFloat(0.8, 1.2); + if(target > 0) + drone_npc.m_iTarget = target; + switch(GetRandomInt(1, 2)) { case 1: diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_specialist.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_specialist.sp index 6b89a6c451..e1d4dfc0d6 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_specialist.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_chemical_specialist.sp @@ -128,9 +128,9 @@ methodmap Chemical_Specialist < CClotBody npc.m_iWearable1 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_pro_smg/c_pro_smg.mdl"); npc.m_iWearable2 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_uberneedle/c_uberneedle.mdl"); - SetEntProp(npc.m_iWearable2, Prop_Send, "m_nSkin", 1); + SetEntProp(npc.m_iWearable2, Prop_Send, "m_nSkin", 1); npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/player/items/engineer/invasion_life_support_system/invasion_life_support_system.mdl"); - SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", 1); + SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", 1); npc.m_iWearable4 = npc.EquipItem("head", "models/workshop/player/items/engineer/hwn2024_mannhattan_protect/hwn2024_mannhattan_protect.mdl"); SetEntProp(npc.m_iWearable4, Prop_Send, "m_nSkin", 1); npc.m_iWearable5 = npc.EquipItem("head", "models/workshop/player/items/engineer/hwn2024_nuclear_necessity/hwn2024_nuclear_necessity.mdl"); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_gasleader.sp b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_gasleader.sp index 21a20a29ec..e39610d183 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_gasleader.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/construction/construction2/victorians/npc_gasleader.sp @@ -237,7 +237,7 @@ static void Gasleader_ClotThink(int iNPC) Explode_Logic_Custom(10.0, -1, npc.index, -1, vecMe, radius, _, 0.75, true, _, false, _, Gasleader_ExplodePost); npc.m_flRangedSpecialDelay = gametime + 0.5; } - float VecI[3]; WorldSpaceCenter(npc.index, VecI); + float VecI[3]; WorldSpaceCenter(npc.index, VecI); for(int entitycount; entitycount Date: Sun, 8 Feb 2026 16:13:35 +0100 Subject: [PATCH 13/24] save --- addons/sourcemod/scripting/zombie_riot/dungeons.sp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/zombie_riot/dungeons.sp b/addons/sourcemod/scripting/zombie_riot/dungeons.sp index 4cc27a5e70..be864eddb5 100644 --- a/addons/sourcemod/scripting/zombie_riot/dungeons.sp +++ b/addons/sourcemod/scripting/zombie_riot/dungeons.sp @@ -2470,7 +2470,7 @@ public void ZRModifs_ModifEnemyChaos(int iNpc) } GiveOneGuranteed = false; RetryBuffGiving = false; - switch(GetRandomInt(1,18)) + switch(GetRandomInt(1,17)) { case 1: { @@ -2601,6 +2601,7 @@ public void ZRModifs_ModifEnemyChaos(int iNpc) else ApplyStatusEffect(iNpc, iNpc, "Perfected Instinct", 999999.9); } + /* case 18: { if(HasSpecificBuff(iNpc, "Xeno Infection") || HasSpecificBuff(iNpc, "Xeno Infection Buff Only")) @@ -2608,6 +2609,7 @@ public void ZRModifs_ModifEnemyChaos(int iNpc) Xeno_Resurgance_Enemy(iNpc); } + */ } } From e077f818dd6cd7ee829fd461816a4035e40ba665 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Sun, 8 Feb 2026 16:13:54 +0100 Subject: [PATCH 14/24] save --- addons/sourcemod/scripting/zombie_riot/dungeons.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/zombie_riot/dungeons.sp b/addons/sourcemod/scripting/zombie_riot/dungeons.sp index be864eddb5..7136f3df66 100644 --- a/addons/sourcemod/scripting/zombie_riot/dungeons.sp +++ b/addons/sourcemod/scripting/zombie_riot/dungeons.sp @@ -2451,7 +2451,7 @@ public void ZRModifs_ModifEnemyChaos(int iNpc) // if(Dungeon_GetEntityZone(iNpc) != Zone_Dungeon && Dungeon_GetEntityZone(iNpc) != Zone_RivalBase) // return; //Rare - if(GetRandomInt(0,RoundToCeil(75.0 * MultiGlobalEnemy)) != 0) + if(GetRandomInt(0,RoundToCeil(35.0 * MultiGlobalEnemy)) != 0) return; b_thisNpcHasAnOutline[iNpc] = true; GiveNpcOutLineLastOrBoss(iNpc, true); From f051cb79e454e20dd36ca2ce166c999e43b888b9 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Sun, 8 Feb 2026 17:09:52 +0100 Subject: [PATCH 15/24] Update final_expidonsa.cfg --- .../sourcemod/configs/zombie_riot/dungeon/final_expidonsa.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sourcemod/configs/zombie_riot/dungeon/final_expidonsa.cfg b/addons/sourcemod/configs/zombie_riot/dungeon/final_expidonsa.cfg index 63c5b98cae..f365925e22 100644 --- a/addons/sourcemod/configs/zombie_riot/dungeon/final_expidonsa.cfg +++ b/addons/sourcemod/configs/zombie_riot/dungeon/final_expidonsa.cfg @@ -248,7 +248,7 @@ "0.5" // a little teeny tiny time. { "count" "0" - "health" "8000000" + "health" "16000000" "is_boss" "3" "is_immune_to_nuke" "1" "is_health_scaling" "1" From 515881739f454378c20712269d05f845e6801754 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Mon, 9 Feb 2026 15:40:08 +0100 Subject: [PATCH 16/24] save --- .../challenges/boss_battle_roulette/vote.cfg | 11 +++ .../zombie_riot/challenges/bossrush/vote.cfg | 11 +++ .../zombie_riot/challenges/defense/vote.cfg | 11 +++ .../zombie_riot/challenges/laststand/vote.cfg | 11 +++ .../zombie_riot/challenges/melee/vote.cfg | 11 +++ .../challenges/rebeloutpost/vote.cfg | 11 +++ .../zombie_riot/challenges/spybattle/vote.cfg | 11 +++ .../zombie_riot/challenges/survival/vote.cfg | 11 +++ .../sourcemod/configs/zombie_riot/classic.cfg | 11 +++ .../configs/zombie_riot/fastmode.cfg | 11 +++ .../configs/zombie_riot/maps/vsh_.cfg | 11 +++ .../configs/zombie_riot/maps/zr_1city.cfg | 11 +++ .../maps/zr_abandoned_lab_surv.cfg | 11 +++ .../zombie_riot/maps/zr_frigidplace.cfg | 11 +++ .../configs/zombie_riot/maps/zr_mansion.cfg | 11 +++ .../configs/zombie_riot/maps/zr_nova/vote.cfg | 11 +++ .../zombie_riot/maps/zr_novaprospekt_new.cfg | 11 +++ .../configs/zombie_riot/maps/zr_respawn.cfg | 11 +++ .../configs/zombie_riot/maps/zr_xfactor.cfg | 11 +++ .../scripting/shared/status_effects.sp | 7 +- .../scripting/zombie_riot/dungeons.sp | 80 +++++++++++++------ .../scripting/zombie_riot/modifiers.sp | 5 ++ .../roguelike/construction_items.sp | 2 +- .../zombieriot.phrases.item.gift.desc.txt | 8 ++ .../zombieriot.phrases.status_effects.txt | 4 +- 25 files changed, 287 insertions(+), 28 deletions(-) diff --git a/addons/sourcemod/configs/zombie_riot/challenges/boss_battle_roulette/vote.cfg b/addons/sourcemod/configs/zombie_riot/challenges/boss_battle_roulette/vote.cfg index efc4bec2fd..50f6ffa3e1 100644 --- a/addons/sourcemod/configs/zombie_riot/challenges/boss_battle_roulette/vote.cfg +++ b/addons/sourcemod/configs/zombie_riot/challenges/boss_battle_roulette/vote.cfg @@ -24,6 +24,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/challenges/bossrush/vote.cfg b/addons/sourcemod/configs/zombie_riot/challenges/bossrush/vote.cfg index 99891ce8f5..c0e0c7311c 100644 --- a/addons/sourcemod/configs/zombie_riot/challenges/bossrush/vote.cfg +++ b/addons/sourcemod/configs/zombie_riot/challenges/bossrush/vote.cfg @@ -48,6 +48,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/challenges/defense/vote.cfg b/addons/sourcemod/configs/zombie_riot/challenges/defense/vote.cfg index fd8bd68a39..c7b1c10720 100644 --- a/addons/sourcemod/configs/zombie_riot/challenges/defense/vote.cfg +++ b/addons/sourcemod/configs/zombie_riot/challenges/defense/vote.cfg @@ -30,6 +30,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/challenges/laststand/vote.cfg b/addons/sourcemod/configs/zombie_riot/challenges/laststand/vote.cfg index 7827015cf5..7d58cca1fd 100644 --- a/addons/sourcemod/configs/zombie_riot/challenges/laststand/vote.cfg +++ b/addons/sourcemod/configs/zombie_riot/challenges/laststand/vote.cfg @@ -30,6 +30,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/challenges/melee/vote.cfg b/addons/sourcemod/configs/zombie_riot/challenges/melee/vote.cfg index af38b39aa8..1d8bde27ca 100644 --- a/addons/sourcemod/configs/zombie_riot/challenges/melee/vote.cfg +++ b/addons/sourcemod/configs/zombie_riot/challenges/melee/vote.cfg @@ -30,6 +30,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/challenges/rebeloutpost/vote.cfg b/addons/sourcemod/configs/zombie_riot/challenges/rebeloutpost/vote.cfg index 9992ddbeed..9b0af5119d 100644 --- a/addons/sourcemod/configs/zombie_riot/challenges/rebeloutpost/vote.cfg +++ b/addons/sourcemod/configs/zombie_riot/challenges/rebeloutpost/vote.cfg @@ -30,6 +30,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/challenges/spybattle/vote.cfg b/addons/sourcemod/configs/zombie_riot/challenges/spybattle/vote.cfg index b2f508a779..bf39b9b654 100644 --- a/addons/sourcemod/configs/zombie_riot/challenges/spybattle/vote.cfg +++ b/addons/sourcemod/configs/zombie_riot/challenges/spybattle/vote.cfg @@ -30,6 +30,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/challenges/survival/vote.cfg b/addons/sourcemod/configs/zombie_riot/challenges/survival/vote.cfg index 4af729545e..56a5f74ef6 100644 --- a/addons/sourcemod/configs/zombie_riot/challenges/survival/vote.cfg +++ b/addons/sourcemod/configs/zombie_riot/challenges/survival/vote.cfg @@ -25,6 +25,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/classic.cfg b/addons/sourcemod/configs/zombie_riot/classic.cfg index 414c6de85d..f848b1538a 100644 --- a/addons/sourcemod/configs/zombie_riot/classic.cfg +++ b/addons/sourcemod/configs/zombie_riot/classic.cfg @@ -108,6 +108,17 @@ "desc" "Paranormal Activity Desc" "level" "0.75" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/fastmode.cfg b/addons/sourcemod/configs/zombie_riot/fastmode.cfg index 807a311ef4..0dd92d18fd 100644 --- a/addons/sourcemod/configs/zombie_riot/fastmode.cfg +++ b/addons/sourcemod/configs/zombie_riot/fastmode.cfg @@ -105,6 +105,17 @@ "desc" "Paranormal Activity Desc" "level" "0.75" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/maps/vsh_.cfg b/addons/sourcemod/configs/zombie_riot/maps/vsh_.cfg index 5c3685245f..b4465f2974 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/vsh_.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/vsh_.cfg @@ -54,6 +54,17 @@ "desc" "Paranormal Activity Desc" "level" "0.75" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Turbulance" { "func_collect" "Modifier_Collect_Turbolences" diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_1city.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_1city.cfg index e860ef0046..44aef53e16 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_1city.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_1city.cfg @@ -34,6 +34,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_abandoned_lab_surv.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_abandoned_lab_surv.cfg index 23dcc056ff..b6e4b1d960 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_abandoned_lab_surv.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_abandoned_lab_surv.cfg @@ -48,6 +48,17 @@ "desc" "Paranormal Activity Desc" "level" "0.75" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_frigidplace.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_frigidplace.cfg index a9e1cb772c..b5d32b04cc 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_frigidplace.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_frigidplace.cfg @@ -39,6 +39,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_mansion.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_mansion.cfg index 6c5d2fbb75..544e9eecca 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_mansion.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_mansion.cfg @@ -38,6 +38,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_nova/vote.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_nova/vote.cfg index 70bf6178af..0288824f32 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_nova/vote.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_nova/vote.cfg @@ -30,6 +30,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Paranormal Activity" { "func_collect" "Modifier_Collect_ParanormalActivity" diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_novaprospekt_new.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_novaprospekt_new.cfg index 30b81859ee..f2fb47986a 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_novaprospekt_new.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_novaprospekt_new.cfg @@ -32,6 +32,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_respawn.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_respawn.cfg index 0deebdf5a9..4472925ce1 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_respawn.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_respawn.cfg @@ -31,6 +31,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_xfactor.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_xfactor.cfg index fa51a1838a..54ebcc9c66 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_xfactor.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_xfactor.cfg @@ -36,6 +36,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/scripting/shared/status_effects.sp b/addons/sourcemod/scripting/shared/status_effects.sp index 9faaaef86d..5c47529335 100644 --- a/addons/sourcemod/scripting/shared/status_effects.sp +++ b/addons/sourcemod/scripting/shared/status_effects.sp @@ -7348,7 +7348,7 @@ void StatusEffects_Construct2_EnemyModifs() StatusEffect_AddGlobal(data); - strcopy(data.BuffName, sizeof(data.BuffName), "Xeno Infection"); + strcopy(data.BuffName, sizeof(data.BuffName), "Xeno Infection Buff"); strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Xeno"); @@ -7846,9 +7846,12 @@ void Const2_XenoInfect(int entity, int victim, float &healingammount) if(GetTeam(victim) != TFTeam_Red) { - if(HasSpecificBuff(victim, "Xeno Infection") || HasSpecificBuff(victim, "Xeno Infection Buff Only")) + if(HasSpecificBuff(victim, "Xeno Infection Buff") || HasSpecificBuff(victim, "Xeno Infection Buff Only")) return; //infects all teams except red + float maxhealth = float(ReturnEntityMaxHealth(victim)); + if(float(GetEntProp(victim, Prop_Data, "m_iHealth")) >= maxhealth * 0.25) + return; #if defined ZR Xeno_Resurgance_Enemy(victim); #endif diff --git a/addons/sourcemod/scripting/zombie_riot/dungeons.sp b/addons/sourcemod/scripting/zombie_riot/dungeons.sp index 7136f3df66..df25e37fbe 100644 --- a/addons/sourcemod/scripting/zombie_riot/dungeons.sp +++ b/addons/sourcemod/scripting/zombie_riot/dungeons.sp @@ -2432,32 +2432,37 @@ stock int FindByEntityName(const char[] name) return -1; } -public void ZRModifs_ModifEnemyChaos(int iNpc) +public void ZRModifs_ModifEnemyPrefixDuff(int iNpc) { - if(i_NpcInternalId[iNpc] == DungeonLoot_Id() ||i_NpcInternalId[iNpc] == Const2Spawner_Id()) - return; - - fl_Extra_Damage[iNpc] *= 1.10; - int Health = GetEntProp(iNpc, Prop_Data, "m_iMaxHealth"); - SetEntProp(iNpc, Prop_Data, "m_iHealth", RoundToCeil(float(Health) * 1.10)); - SetEntProp(iNpc, Prop_Data, "m_iMaxHealth", RoundToCeil(float(Health) * 1.10)); - + bool DontBuffBaseStats = false; if(b_thisNpcIsABoss[iNpc]) - return; + DontBuffBaseStats = true; + if(b_thisNpcIsARaid[iNpc]) + { + DontBuffBaseStats = true; + RaidModeTime = FAR_FUTURE; + } if(i_IsABuilding[iNpc]) return; if(i_NpcIsABuilding[iNpc]) return; -// if(Dungeon_GetEntityZone(iNpc) != Zone_Dungeon && Dungeon_GetEntityZone(iNpc) != Zone_RivalBase) -// return; - //Rare - if(GetRandomInt(0,RoundToCeil(35.0 * MultiGlobalEnemy)) != 0) + + if(!DontBuffBaseStats && GetRandomInt(0,RoundToCeil(15.0 * MultiGlobalEnemy)) != 0) return; - b_thisNpcHasAnOutline[iNpc] = true; - GiveNpcOutLineLastOrBoss(iNpc, true); - SetEntProp(iNpc, Prop_Data, "m_iHealth", RoundToCeil(float(ReturnEntityMaxHealth(iNpc)) * 3.0)); - SetEntProp(iNpc, Prop_Data, "m_iMaxHealth", RoundToCeil(float(ReturnEntityMaxHealth(iNpc)) * 3.0)); - fl_Extra_Damage[iNpc] *= 1.2; + + if(!DontBuffBaseStats) + { + b_thisNpcHasAnOutline[iNpc] = true; + GiveNpcOutLineLastOrBoss(iNpc, true); + SetEntProp(iNpc, Prop_Data, "m_iHealth", RoundToCeil(float(ReturnEntityMaxHealth(iNpc)) * 3.0)); + SetEntProp(iNpc, Prop_Data, "m_iMaxHealth", RoundToCeil(float(ReturnEntityMaxHealth(iNpc)) * 3.0)); + fl_Extra_Damage[iNpc] *= 1.25; + } + ZRModifs_GiveRandomPrefix(iNpc); + //This is a unique enemy, give mega buffs +} +public void ZRModifs_GiveRandomPrefix(int iNpc) +{ bool RetryBuffGiving = false; bool GiveOneGuranteed = true; int MaxHits = 0; @@ -2470,7 +2475,7 @@ public void ZRModifs_ModifEnemyChaos(int iNpc) } GiveOneGuranteed = false; RetryBuffGiving = false; - switch(GetRandomInt(1,17)) + switch(GetRandomInt(1,18)) { case 1: { @@ -2601,17 +2606,46 @@ public void ZRModifs_ModifEnemyChaos(int iNpc) else ApplyStatusEffect(iNpc, iNpc, "Perfected Instinct", 999999.9); } - /* + case 18: { - if(HasSpecificBuff(iNpc, "Xeno Infection") || HasSpecificBuff(iNpc, "Xeno Infection Buff Only")) + if(HasSpecificBuff(iNpc, "Xeno Infection Buff") || HasSpecificBuff(iNpc, "Xeno Infection Buff Only")) RetryBuffGiving = true; Xeno_Resurgance_Enemy(iNpc); } - */ + } } +} +public void ZRModifs_ModifEnemyChaos(int iNpc) +{ + if(i_NpcInternalId[iNpc] == DungeonLoot_Id() ||i_NpcInternalId[iNpc] == Const2Spawner_Id()) + return; + + fl_Extra_Damage[iNpc] *= 1.10; + int Health = GetEntProp(iNpc, Prop_Data, "m_iMaxHealth"); + SetEntProp(iNpc, Prop_Data, "m_iHealth", RoundToCeil(float(Health) * 1.10)); + SetEntProp(iNpc, Prop_Data, "m_iMaxHealth", RoundToCeil(float(Health) * 1.10)); + + if(b_thisNpcIsABoss[iNpc]) + return; + if(i_IsABuilding[iNpc]) + return; + if(i_NpcIsABuilding[iNpc]) + return; +// if(Dungeon_GetEntityZone(iNpc) != Zone_Dungeon && Dungeon_GetEntityZone(iNpc) != Zone_RivalBase) +// return; + //Rare + if(GetRandomInt(0,RoundToCeil(35.0 * MultiGlobalEnemy)) != 0) + return; + + b_thisNpcHasAnOutline[iNpc] = true; + GiveNpcOutLineLastOrBoss(iNpc, true); + SetEntProp(iNpc, Prop_Data, "m_iHealth", RoundToCeil(float(ReturnEntityMaxHealth(iNpc)) * 3.0)); + SetEntProp(iNpc, Prop_Data, "m_iMaxHealth", RoundToCeil(float(ReturnEntityMaxHealth(iNpc)) * 3.0)); + fl_Extra_Damage[iNpc] *= 1.2; + ZRModifs_GiveRandomPrefix(iNpc); //This is a unique enemy, give mega buffs } diff --git a/addons/sourcemod/scripting/zombie_riot/modifiers.sp b/addons/sourcemod/scripting/zombie_riot/modifiers.sp index c5f4eb5517..246759619a 100644 --- a/addons/sourcemod/scripting/zombie_riot/modifiers.sp +++ b/addons/sourcemod/scripting/zombie_riot/modifiers.sp @@ -9,6 +9,7 @@ static int CurrentModifActive = 0; #define OLD_TIMES 3 #define TURBOLENCES 4 #define PARANORMAL_ACTIVITY 5 +#define PREFIX_GALORE 6 void Modifier_MiniBossSpawn(bool &spawns) { @@ -54,6 +55,10 @@ public void Modifier_Collect_SecondaryMercs() { CurrentModifActive = SECONDARY_MERCS; } +public void Modifier_Collect_Prefix_Galore() +{ + CurrentModifActive = PREFIX_GALORE; +} public void Modifier_Remove_SecondaryMercs() { diff --git a/addons/sourcemod/scripting/zombie_riot/roguelike/construction_items.sp b/addons/sourcemod/scripting/zombie_riot/roguelike/construction_items.sp index 9f3b25ec64..b9a4712353 100644 --- a/addons/sourcemod/scripting/zombie_riot/roguelike/construction_items.sp +++ b/addons/sourcemod/scripting/zombie_riot/roguelike/construction_items.sp @@ -368,7 +368,7 @@ public void Xeno_Resurgance_Enemy(int entity) return; if(view_as(entity).m_iBleedType != BLEEDTYPE_XENO) - ApplyStatusEffect(entity, entity, "Xeno Infection", 9999.9); + ApplyStatusEffect(entity, entity, "Xeno Infection Buff", 9999.9); else ApplyStatusEffect(entity, entity, "Xeno Infection Buff Only", 9999.9); } diff --git a/addons/sourcemod/translations/zombieriot.phrases.item.gift.desc.txt b/addons/sourcemod/translations/zombieriot.phrases.item.gift.desc.txt index b52d6e767a..7cac14f0be 100644 --- a/addons/sourcemod/translations/zombieriot.phrases.item.gift.desc.txt +++ b/addons/sourcemod/translations/zombieriot.phrases.item.gift.desc.txt @@ -2521,6 +2521,14 @@ "it" "Il primo gruppo di mercenari ha già fallito.\n 35 nemici in più, si riproducono 33% più velocemente, 15% in più sono vivi contemporaneamente. infliggono +15% dmg, +25% dmg ai cad, hanno 50% + HP, +4% più velocemente. i nemici guariscono 50% in più." "ko" "최초로 출격한 용병들은 실패했습니다.\n웨이브 적 수량 +35%, 생성 속도 +33%, 한번에 존재하는 적의 수 +15%\n적 피해량 +15%, 구조물 대상 피해량 +25%, 체력 +50%, 이동 속도 +4%\n적들의 체력 회복량 +50%" } + "Prefixes Galore" + { + "en" "Prefixes Galore" + } + "Prefixes Galore Desc" + { + "en" "Prepare for aboslute hell!\nEnemies have a chance to obtain prefixes, if they do, they gain massive buffs aswell.\nBosses and raids gain prefixes guranteed but arent extra buffed\nRaids have infinite time.\nPrefixes can stack." + } "Paranormal Activity" { "en" "Paranormal Activity" diff --git a/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt b/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt index 30ebdc9776..9183930160 100644 --- a/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt +++ b/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt @@ -2804,12 +2804,12 @@ "en" "Npc Gains 30% Resistance, 300% Damage, 2x Thinkspeed" "ko" "NPC의 저항력이 30%, 공격 피해량이 300%, 생각하는 속도가 2배 증가합니다." } - "Xeno Infection" + "Xeno Infection Buff" { "en" "Xeno Infection" "ko" "제노에 감염된" } - "Xeno Infection Desc" + "Xeno Infection Buff Desc" { "en" "Npc Gains 35% Resistance, 40% Damage, but thinks 10% slower, and regens over time upto 1.35x max health, if above 25% max health, gain immensive buffs untill below\ninfects any enemy with xeno aswell." "ko" "NPC 저항력 35%, 피해량 40% 증가. 생각 속도 10% 감소. 최대 체력의 1.35배까지 재생. 체력이 25% 이상이라면 그 이하가 될 때까지 강력한 버프 획득\n다른 적에게도 제노를 감염시킴" From 34fcfaa14ae99d90f3eb877fcc225fd4a4150931 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Mon, 9 Feb 2026 15:44:31 +0100 Subject: [PATCH 17/24] save --- addons/sourcemod/scripting/zombie_riot/dungeons.sp | 2 +- addons/sourcemod/scripting/zombie_riot/modifiers.sp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/zombie_riot/dungeons.sp b/addons/sourcemod/scripting/zombie_riot/dungeons.sp index df25e37fbe..01eb03d6af 100644 --- a/addons/sourcemod/scripting/zombie_riot/dungeons.sp +++ b/addons/sourcemod/scripting/zombie_riot/dungeons.sp @@ -2576,7 +2576,7 @@ public void ZRModifs_GiveRandomPrefix(int iNpc) } case 15: { - if(Elemental_DamageRatio(iNpc, Element_Warped) > 0.0) + if(b_thisNpcIsARaid[iNpc] || Elemental_DamageRatio(iNpc, Element_Warped) > 0.0) { RetryBuffGiving = true; } diff --git a/addons/sourcemod/scripting/zombie_riot/modifiers.sp b/addons/sourcemod/scripting/zombie_riot/modifiers.sp index 246759619a..5ae1e42dd0 100644 --- a/addons/sourcemod/scripting/zombie_riot/modifiers.sp +++ b/addons/sourcemod/scripting/zombie_riot/modifiers.sp @@ -379,6 +379,10 @@ void ZRModifs_CharBuffToAdd(char[] data) { FormatEx(data, 6, "P"); } + case PREFIX_GALORE: + { + FormatEx(data, 6, "PG"); + } } } From bd6a4d1fcb9ebf0dacf6b26a0ed027dd84a6e502 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:55:08 +0100 Subject: [PATCH 18/24] Update status_effects.sp --- addons/sourcemod/scripting/shared/status_effects.sp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/sourcemod/scripting/shared/status_effects.sp b/addons/sourcemod/scripting/shared/status_effects.sp index 5c47529335..fe69e8559e 100644 --- a/addons/sourcemod/scripting/shared/status_effects.sp +++ b/addons/sourcemod/scripting/shared/status_effects.sp @@ -7712,6 +7712,8 @@ static void Const2_SefHeal_Timer(int entity, StatusEffect Apply_MasterStatusEffe E_AL_StatusEffects[entity].SetArray(ArrayPosition, Apply_StatusEffect); float maxhealth = float(ReturnEntityMaxHealth(entity)); + if(b_thisNpcIsARaid[entity] || b_thisNpcIsABoss[entity]) + maxhealth *= 0.01; HealEntityGlobal(entity, entity, maxhealth / 5.0, 1.0, 0.0, HEAL_SELFHEAL); } From 72963e9c599f9051138ec271c48f82916f57cca5 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Mon, 9 Feb 2026 23:58:55 +0100 Subject: [PATCH 19/24] save --- .../configs/zombie_riot/maps/zr_defense.cfg | 11 + .../configs/zombie_riot/maps/zr_matrix.cfg | 58 ++ .../zombie_riot/maps/zr_summercamp.cfg | 58 ++ addons/sourcemod/scripting/shared/sdkhooks.sp | 21 + .../scripting/shared/status_effects.sp | 870 +++++++++++++++++- addons/sourcemod/scripting/shared/stocks.sp | 4 +- .../scripting/zombie_riot/dungeons.sp | 127 ++- .../zombie_riot/object/obj_vintulum_bomb.sp | 43 +- .../zombieriot.phrases.status_effects.txt | 366 +++++++- .../zombieriot.phrases.zombienames.txt | 4 + 10 files changed, 1513 insertions(+), 49 deletions(-) diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_defense.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_defense.cfg index cfffb393a4..adc42f5421 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_defense.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_defense.cfg @@ -45,6 +45,17 @@ "desc" "Chaos Intrusion Desc" "level" "0.5" } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } "Secondary Mercs" { "func_collect" "Modifier_Collect_SecondaryMercs" diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_matrix.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_matrix.cfg index 3e966102d5..797644686a 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_matrix.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_matrix.cfg @@ -22,6 +22,64 @@ "level" "70" } } + "Modifiers" + { + "Chaos Intrusion" + { + "func_collect" "Modifier_Collect_ChaosIntrusion" + "func_remove" "Modifier_Remove_ChaosIntrusion" + "func_ally" "" + "func_enemy" "ZRModifs_ChaosIntrusionNPC" + "func_weapon" "" + + "desc" "Chaos Intrusion Desc" + "level" "0.5" + } + "Paranormal Activity" + { + "func_collect" "Modifier_Collect_ParanormalActivity" + "func_remove" "Modifier_Remove_ParanormalActivity" + "func_ally" "" + "func_enemy" "ZRModifs_ParanormalActivityNPC" + "func_weapon" "" + + "desc" "Paranormal Activity Desc" + "level" "0.75" + } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } + "Secondary Mercs" + { + "func_collect" "Modifier_Collect_SecondaryMercs" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "Modifier_RecolourAlly_SecondaryMercs" + "func_enemy" "ZRModifs_SecondaryMercsNPC" + "func_weapon" "" + + "desc" "Secondary Mercs Desc" + "level" "2.0" + } + "Old Times" + { + "func_collect" "Modifier_Collect_OldTimes" + "func_remove" "Modifier_Remove_OldTimes" + "func_ally" "" + "func_enemy" "ZRModifs_OldTimesNPC" + "func_weapon" "" + + "desc" "Old Times Desc" + "level" "3.0" + } + } } "MiniBoss" { diff --git a/addons/sourcemod/configs/zombie_riot/maps/zr_summercamp.cfg b/addons/sourcemod/configs/zombie_riot/maps/zr_summercamp.cfg index b977fd61db..b64af772fc 100644 --- a/addons/sourcemod/configs/zombie_riot/maps/zr_summercamp.cfg +++ b/addons/sourcemod/configs/zombie_riot/maps/zr_summercamp.cfg @@ -28,6 +28,64 @@ "level" "0000" } } + "Modifiers" + { + "Chaos Intrusion" + { + "func_collect" "Modifier_Collect_ChaosIntrusion" + "func_remove" "Modifier_Remove_ChaosIntrusion" + "func_ally" "" + "func_enemy" "ZRModifs_ChaosIntrusionNPC" + "func_weapon" "" + + "desc" "Chaos Intrusion Desc" + "level" "0.5" + } + "Paranormal Activity" + { + "func_collect" "Modifier_Collect_ParanormalActivity" + "func_remove" "Modifier_Remove_ParanormalActivity" + "func_ally" "" + "func_enemy" "ZRModifs_ParanormalActivityNPC" + "func_weapon" "" + + "desc" "Paranormal Activity Desc" + "level" "0.75" + } + "Prefixes Galore" + { + "func_collect" "Modifier_Collect_Prefix_Galore" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "" + "func_enemy" "ZRModifs_ModifEnemyPrefixDuff" + "func_weapon" "" + + "desc" "Prefixes Galore Desc" + "level" "2.0" + } + "Secondary Mercs" + { + "func_collect" "Modifier_Collect_SecondaryMercs" + "func_remove" "Modifier_Remove_SecondaryMercs" + "func_ally" "Modifier_RecolourAlly_SecondaryMercs" + "func_enemy" "ZRModifs_SecondaryMercsNPC" + "func_weapon" "" + + "desc" "Secondary Mercs Desc" + "level" "2.0" + } + "Old Times" + { + "func_collect" "Modifier_Collect_OldTimes" + "func_remove" "Modifier_Remove_OldTimes" + "func_ally" "" + "func_enemy" "ZRModifs_OldTimesNPC" + "func_weapon" "" + + "desc" "Old Times Desc" + "level" "3.0" + } + } } "MiniBoss" { diff --git a/addons/sourcemod/scripting/shared/sdkhooks.sp b/addons/sourcemod/scripting/shared/sdkhooks.sp index b1c143953f..d72715f8c4 100644 --- a/addons/sourcemod/scripting/shared/sdkhooks.sp +++ b/addons/sourcemod/scripting/shared/sdkhooks.sp @@ -2480,6 +2480,7 @@ public Action SDKHook_AmbientSoundHook(char sample[PLATFORM_MAX_PATH], int &enti return Plugin_Continue; } +bool LouderSoundStop = false; public Action SDKHook_NormalSHook(int clients[MAXPLAYERS], int &numClients, char sample[PLATFORM_MAX_PATH], int &entity, int &channel, float &volume, int &level, int &pitch, int &flags, char soundEntry[PLATFORM_MAX_PATH], int &seed) @@ -2512,6 +2513,26 @@ public Action SDKHook_NormalSHook(int clients[MAXPLAYERS], int &numClients, char */ #if defined ZR + + if(StrContains(sample, "#", true) != -1) + { + + } + else + { + if(!LouderSoundStop && HasSpecificBuff(entity, "Loud Prefix")) + { + level += 20; + LouderSoundStop = true; + for(int loop1=0; loop1 MaxClients && entity < MAXENTITIES && !b_NpcHasDied[entity] && !(flags & SND_STOP)) { diff --git a/addons/sourcemod/scripting/shared/status_effects.sp b/addons/sourcemod/scripting/shared/status_effects.sp index fe69e8559e..b1ff0cccd4 100644 --- a/addons/sourcemod/scripting/shared/status_effects.sp +++ b/addons/sourcemod/scripting/shared/status_effects.sp @@ -149,6 +149,14 @@ static const char XenoInfect[][] = { "items/powerup_pickup_plague_infected.wav", }; +static const char BoingSound[][] = +{ + "player/taunt_springrider_squeak1.wav", + "player/taunt_springrider_squeak2.wav", + "player/taunt_springrider_squeak3.wav", + "player/taunt_springrider_squeak4.wav", + "player/taunt_springrider_squeak5.wav", +}; void ResetExplainBuffStatus(int client) { DisplayChatBuffCD[client] = 0.0; @@ -171,6 +179,7 @@ void InitStatusEffects() AL_StatusEffects = new ArrayList(sizeof(StatusEffect)); PrecacheSoundArray(MissSound); PrecacheSoundArray(XenoInfect); + PrecacheSoundArray(BoingSound); DeleteStatusEffectsFromAll(); //clear all existing ones @@ -7094,7 +7103,7 @@ void StatusEffects_Construct2_EnemyModifs() strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Big"); //-1.0 means unused - data.DamageTakenMulti = 0.25; + data.DamageTakenMulti = 0.35; data.DamageDealMulti = -1.0; data.MovementspeedModif = -1.0; data.AttackspeedBuff = -1.0; @@ -7110,7 +7119,7 @@ void StatusEffects_Construct2_EnemyModifs() strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Strong"); //-1.0 means unused data.DamageTakenMulti = -1.0; - data.DamageDealMulti = 3.0; + data.DamageDealMulti = 2.5; data.MovementspeedModif = -1.0; data.AttackspeedBuff = -1.0; data.Positive = true; @@ -7251,6 +7260,22 @@ void StatusEffects_Construct2_EnemyModifs() data.TimerRepeatCall_Func = Const2_SefHeal_Timer; StatusEffect_AddGlobal(data); + strcopy(data.BuffName, sizeof(data.BuffName), "Armoring Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Armoring"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = INVALID_FUNCTION; + data.OnBuffEndOrDeleted = INVALID_FUNCTION; + data.TimerRepeatCall_Func = Const2_Armoring_Timer; + StatusEffect_AddGlobal(data); + strcopy(data.BuffName, sizeof(data.BuffName), "Laggy"); strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty @@ -7336,8 +7361,8 @@ void StatusEffects_Construct2_EnemyModifs() strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), "TF"); //dont display above head, so empty strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "The First"); //-1.0 means unused - data.DamageTakenMulti = 0.3; - data.DamageDealMulti = 2.0; + data.DamageTakenMulti = 0.5; + data.DamageDealMulti = 1.0; data.MovementspeedModif = -1.0; data.AttackspeedBuff = (1.0 / 2.0); data.Positive = true; @@ -7385,8 +7410,8 @@ void StatusEffects_Construct2_EnemyModifs() strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Perfected Instinct"); //-1.0 means unused - data.DamageTakenMulti = 0.3; - data.DamageDealMulti = 2.0; + data.DamageTakenMulti = 0.6; + data.DamageDealMulti = 1.75; data.MovementspeedModif = -1.0; data.AttackspeedBuff = (1.0 / 1.5); data.Positive = true; @@ -7413,7 +7438,293 @@ void StatusEffects_Construct2_EnemyModifs() data.OnBuffEndOrDeleted = INVALID_FUNCTION; data.TimerRepeatCall_Func = INVALID_FUNCTION; StatusEffect_AddGlobal(data); -} + + + strcopy(data.BuffName, sizeof(data.BuffName), "Motivating Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Motivating"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnTakeDamage_TakenFunc = INVALID_FUNCTION; + data.OnBuffStarted = INVALID_FUNCTION; + data.OnBuffEndOrDeleted = INVALID_FUNCTION; + data.TimerRepeatCall_Func = Const2_Motivation_Do; + StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Invisible Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Invisible"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = Const2Modifs_Paranormal_Start; + data.OnBuffEndOrDeleted = INVALID_FUNCTION; + data.TimerRepeatCall_Func = INVALID_FUNCTION; + StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Asexual Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Asexual"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = INVALID_FUNCTION; + data.OnBuffEndOrDeleted = Const2Modifs_Asexual_End; + data.TimerRepeatCall_Func = INVALID_FUNCTION; + StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Glug Infested Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Glug Infested"); + //-1.0 means unused + data.DamageTakenMulti = 0.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = Const2Modifs_Glug_Start; + data.OnBuffEndOrDeleted = Const2Modifs_Glug_End; + data.OnTakeDamage_TakenFunc = Glug_TakeDamage_Spread; + StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Explosive Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Explosive"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = Const2Modifs_Explosive_Start; + data.OnBuffEndOrDeleted = Const2Modifs_Explosive_End; + data.OnTakeDamage_TakenFunc = INVALID_FUNCTION; + StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Stalker Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Stalker"); + //-1.0 means unused + data.DamageTakenMulti = 0.01; + data.DamageDealMulti = 5.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = Const2Modifs_Stalker_Start; + data.OnBuffEndOrDeleted = INVALID_FUNCTION; + data.OnTakeDamage_TakenFunc = INVALID_FUNCTION; + StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Stalker Prefix Nerf"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), ""); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = 0.75; + data.AttackspeedBuff = -1.0; + data.Positive = false; + data.ElementalLogic = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = INVALID_FUNCTION; + data.OnBuffEndOrDeleted = INVALID_FUNCTION; + data.OnTakeDamage_TakenFunc = INVALID_FUNCTION; + StatusEffect_AddGlobal(data); + data.ElementalLogic = false; + + + strcopy(data.BuffName, sizeof(data.BuffName), "Disco Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Disco"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = Disco_Start; + data.OnBuffEndOrDeleted = Perfected_InstinctEnd; + data.TimerRepeatCall_Func = Disco_Timer; + StatusEffect_AddGlobal(data); + + + strcopy(data.BuffName, sizeof(data.BuffName), "Toxic Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Toxic"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = Toxic_Start; + data.OnBuffEndOrDeleted = Perfected_InstinctEnd; + data.TimerRepeatCall_Func = Toxic_Think_Do; + StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Boing Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Boing"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = INVALID_FUNCTION; + data.OnBuffEndOrDeleted = INVALID_FUNCTION; + data.TimerRepeatCall_Func = Boing_Think_Do; + StatusEffect_AddGlobal(data); + data.TimerRepeatCall_Func = INVALID_FUNCTION; + + + strcopy(data.BuffName, sizeof(data.BuffName), "Knockback Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Knockback"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = INVALID_FUNCTION; + data.OnBuffEndOrDeleted = INVALID_FUNCTION; + data.OnTakeDamage_PostAttacker = Knocback_Prefix_TakeDamageAttackerPost; + StatusEffect_AddGlobal(data); + + data.OnTakeDamage_PostAttacker = INVALID_FUNCTION; + + strcopy(data.BuffName, sizeof(data.BuffName), "Loud Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Loud"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = INVALID_FUNCTION; + data.OnBuffEndOrDeleted = INVALID_FUNCTION; + data.TimerRepeatCall_Func = INVALID_FUNCTION; + StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Legendary Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Legendary"); + //-1.0 means unused + data.DamageTakenMulti = 0.0; + data.DamageDealMulti = 0.0; + data.MovementspeedModif = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = Legendary_Prefix_Start; + data.OnBuffEndOrDeleted = Perfected_InstinctEnd; + data.OnTakeDamage_TakenFunc = Legendary_Prefix_DamageTakenFunc; + data.OnTakeDamage_DealFunc = Legendary_Prefix_DamageDealFunc; + StatusEffect_AddGlobal(data); + + data.OnTakeDamage_TakenFunc = INVALID_FUNCTION; + data.OnTakeDamage_DealFunc = INVALID_FUNCTION; + + strcopy(data.BuffName, sizeof(data.BuffName), "Ragebaiter Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Ragebaiter"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = INVALID_FUNCTION; + data.OnBuffEndOrDeleted = INVALID_FUNCTION; + data.TimerRepeatCall_Func = Ragebaiter_Think_Do; + StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Semi Healthy Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Semi Healthy"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = -1.0; + data.AttackspeedBuff = -1.0; + data.Positive = true; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = SemiHealthy_Start; + data.OnBuffEndOrDeleted = SemiHealthy_End; + data.TimerRepeatCall_Func = INVALID_FUNCTION; + StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Fat Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Fat"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = 0.25; + data.AttackspeedBuff = -1.0; + data.Positive = false; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = Const2Modifs_Fat_Start; + data.OnBuffEndOrDeleted = Const2Modifs_Fat_End; + data.TimerRepeatCall_Func = INVALID_FUNCTION; + StatusEffect_AddGlobal(data); + + strcopy(data.BuffName, sizeof(data.BuffName), "Modifier+ Prefix"); + strcopy(data.HudDisplay, sizeof(data.HudDisplay), ""); + strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty + strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Modifier+"); + //-1.0 means unused + data.DamageTakenMulti = -1.0; + data.DamageDealMulti = -1.0; + data.MovementspeedModif = 0.25; + data.AttackspeedBuff = -1.0; + data.Positive = false; + data.ShouldScaleWithPlayerCount = false; + data.OnBuffStarted = Const2Modifs_Modifier_Start; + data.OnBuffEndOrDeleted = INVALID_FUNCTION; + data.TimerRepeatCall_Func = INVALID_FUNCTION; + StatusEffect_AddGlobal(data); + +} void Const2Modifs_Haste_Start(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) @@ -7537,8 +7848,13 @@ void Const2Modifs_Vampire_TakeDamageAttackerPost(int attacker, int victim, float { if(attacker == victim) return; - - HealEntityGlobal(attacker, attacker, damage * 10, 2.0, 0.0, HEAL_SELFHEAL); + float HealBy = damage * 10.0; + float maxhealth = float(ReturnEntityMaxHealth(attacker)); + maxhealth *= 0.25; + if(HealBy >= maxhealth) + HealBy = maxhealth; + + HealEntityGlobal(attacker, attacker, HealBy, 2.0, 0.0, HEAL_SELFHEAL); } @@ -7597,11 +7913,11 @@ static void Const2_Sprayer_Timer(int entity, StatusEffect Apply_MasterStatusEffe int ArrayPosition = E_AL_StatusEffects[entity].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); Apply_StatusEffect.DataForUse = GetGameTime() + 2.0; E_AL_StatusEffects[entity].SetArray(ArrayPosition, Apply_StatusEffect); - float DamageDeal = 1000.0; + float DamageDeal = 250.0; #if defined ZR DamageDeal = float(CurrentCash); #endif - DamageDeal *= 0.01; + DamageDeal *= 0.005; if(DamageDeal <= 50.0) DamageDeal = 50.0; @@ -7716,17 +8032,32 @@ static void Const2_SefHeal_Timer(int entity, StatusEffect Apply_MasterStatusEffe maxhealth *= 0.01; HealEntityGlobal(entity, entity, maxhealth / 5.0, 1.0, 0.0, HEAL_SELFHEAL); } - - - -static void Const2_Laggy_Timer(int entity, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +static void Const2_Armoring_Timer(int entity, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) { if(Apply_StatusEffect.DataForUse > GetGameTime()) { return; } int ArrayPosition = E_AL_StatusEffects[entity].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); - Apply_StatusEffect.DataForUse = GetGameTime() + GetRandomFloat(2.0 , 3.5); + Apply_StatusEffect.DataForUse = GetGameTime() + 3.0; + E_AL_StatusEffects[entity].SetArray(ArrayPosition, Apply_StatusEffect); + + float maxhealth = float(ReturnEntityMaxHealth(entity)); + if(b_thisNpcIsARaid[entity] || b_thisNpcIsABoss[entity]) + maxhealth *= 0.01; + GrantEntityArmor(entity, false, 1.0, 0.25, 0, maxhealth / 5.0); +} + + + +static void Const2_Laggy_Timer(int entity, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + if(Apply_StatusEffect.DataForUse > GetGameTime()) + { + return; + } + int ArrayPosition = E_AL_StatusEffects[entity].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); + Apply_StatusEffect.DataForUse = GetGameTime() + GetRandomFloat(2.0 , 3.5); E_AL_StatusEffects[entity].SetArray(ArrayPosition, Apply_StatusEffect); @@ -7852,7 +8183,7 @@ void Const2_XenoInfect(int entity, int victim, float &healingammount) return; //infects all teams except red float maxhealth = float(ReturnEntityMaxHealth(victim)); - if(float(GetEntProp(victim, Prop_Data, "m_iHealth")) >= maxhealth * 0.25) + if(float(GetEntProp(victim, Prop_Data, "m_iHealth")) >= maxhealth * 0.5) return; #if defined ZR Xeno_Resurgance_Enemy(victim); @@ -7934,6 +8265,11 @@ float Perfected_Instinct_Dodge(int attacker, int victim, StatusEffect Apply_Mast TE_SendToAll(); int Rand = GetRandomInt(0, sizeof(MissSound) - 1); EmitSoundToAll(MissSound[Rand], victim, _, 80); + if(Apply_StatusEffect.DataForUse > GetGameTime()) + return 0.0; + int ArrayPosition = E_AL_StatusEffects[victim].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); + Apply_StatusEffect.DataForUse = GetGameTime() + 1.0; + E_AL_StatusEffects[victim].SetArray(ArrayPosition, Apply_StatusEffect); ApplyStatusEffect(victim, victim, "Perfected Instinct Speed", 0.35); return 0.0; } @@ -7980,4 +8316,504 @@ void Const2Modifs_Xeno_End(int victim, StatusEffect Apply_MasterStatusEffect, E_ CClotBody npc = view_as(victim); npc.m_iBleedType = RoundToNearest(Apply_StatusEffect.DataForUse); SetEntityRenderColor_NpcAll(victim, (1.0 / 0.15), (1.0 / 0.15), (1.0 / 0.15)); +} + + +static void Const2_Motivation_Do(int entity, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + if(Apply_StatusEffect.DataForUse > GetGameTime()) + { + return; + } + int ArrayPosition = E_AL_StatusEffects[entity].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); + Apply_StatusEffect.DataForUse = GetGameTime() + 0.5; + E_AL_StatusEffects[entity].SetArray(ArrayPosition, Apply_StatusEffect); + + //infect + ContractedMotivatorEffect2(entity, 300.0); + ExpidonsaGroupHeal(entity, + 300.0, + 99, + 0.0, + 1.0, + false, + ConstractedMotivatorBuffs , + _, + true); +} + +void ContractedMotivatorEffect2(int entity, float range) +{ + float ProjectileLoc[3]; + GetEntPropVector(entity, Prop_Data, "m_vecAbsOrigin", ProjectileLoc); + spawnRing_Vectors(ProjectileLoc, 0.1, 0.0, 0.0, 10.0, "materials/sprites/laserbeam.vmt", 200, 200, 65, 100, 1, 0.5, 5.0, 0.1, 3, range * 2.0); +} + + + +void Const2Modifs_Paranormal_Start(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + //not an npc, ignore. + if(!b_ThisWasAnNpc[victim]) + return; + ZRModifs_ParanormalActivityNPC(victim); +} +void Const2Modifs_Asexual_End(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + //not an npc, ignore. + if(!IsValidEntity(victim) || !b_ThisWasAnNpc[victim]) + return; + + float maxhealth = float(ReturnEntityMaxHealth(victim)); + maxhealth *= 0.5; + float pos[3]; GetEntPropVector(victim, Prop_Data, "m_vecAbsOrigin", pos); + pos[2] += 50.0; + float ang[3]; GetEntPropVector(victim, Prop_Data, "m_angRotation", ang); + int summon = NPC_CreateById(i_NpcInternalId[victim], -1, pos, ang, GetTeam(victim)); + if(summon > MaxClients) + { + fl_Extra_Damage[summon] = fl_Extra_Damage[victim]; + fl_Extra_Speed[summon] = fl_Extra_Speed[victim]; + fl_Extra_RangedArmor[summon] = fl_Extra_RangedArmor[victim]; + fl_Extra_MeleeArmor[summon] = fl_Extra_MeleeArmor[victim]; + SetEntProp(victim, Prop_Data, "m_iHealth", RoundToNearest(maxhealth)); + SetEntProp(victim, Prop_Data, "m_iMaxHealth", RoundToNearest(maxhealth)); + float flPos[3]; + flPos = pos; + flPos[2] += 300.0; + flPos[0] += GetRandomInt(0,1) ? GetRandomFloat(-200.0, -100.0) : GetRandomFloat(100.0, 200.0); + flPos[1] += GetRandomInt(0,1) ? GetRandomFloat(-200.0, -100.0) : GetRandomFloat(200.0, 200.0); + CClotBody npc = view_as(summon); + npc.SetVelocity({0.0,0.0,0.0}); + PluginBot_Jump(summon, flPos); + ApplyStatusEffect(summon, summon, "Unstoppable Force", 2.0); + ZRModifs_GiveRandomPrefix(summon); + } +} + + +void Const2Modifs_Glug_Start(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + //not an npc, ignore. + if(!b_ThisWasAnNpc[victim]) + return; + + SetEntityRenderColor_NpcAll(victim, 1.5, 1.5, 0.15); +} +void Const2Modifs_Glug_End(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + //not an npc, ignore. + if(!IsValidEntity(victim) || !b_ThisWasAnNpc[victim]) + return; + + SetEntityRenderColor_NpcAll(victim, (1.0 / 1.5), (1.0 / 0.15), (1.0 / 0.15)); +} + + +float Glug_TakeDamage_Spread(int attacker, int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect, int damagetype) +{ + if(CheckInHud()) + return 1.0; + + if(Apply_StatusEffect.DataForUse > GetGameTime()) + { + return 1.0; + } + int ArrayPosition = E_AL_StatusEffects[victim].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); + Apply_StatusEffect.DataForUse = GetGameTime() + 10.0; + E_AL_StatusEffects[victim].SetArray(ArrayPosition, Apply_StatusEffect); + + float maxhealth = float(ReturnEntityMaxHealth(victim)); + maxhealth *= 0.25; + if(b_thisNpcIsARaid[victim] || b_thisNpcIsABoss[victim]) + maxhealth *= 0.025; + + float pos[3]; GetEntPropVector(victim, Prop_Data, "m_vecAbsOrigin", pos); + float ang[3]; GetEntPropVector(victim, Prop_Data, "m_angRotation", ang); + int summon = NPC_CreateByName("npc_glug", -1, pos, ang, GetTeam(victim), ""); + if(summon > MaxClients) + { + float DamageDeal = 10.0; +#if defined ZR + DamageDeal = float(CurrentCash); +#endif + DamageDeal *= 0.01; + if(DamageDeal <= 1.0) + DamageDeal = 1.0; + + if(DamageDeal > 100.0) + DamageDeal = 100.0; + fl_Extra_Damage[summon] *= DamageDeal; + fl_Extra_Speed[summon] = fl_Extra_Speed[victim]; + fl_Extra_RangedArmor[summon] = fl_Extra_RangedArmor[victim]; + fl_Extra_MeleeArmor[summon] = fl_Extra_MeleeArmor[victim]; + SetEntProp(summon, Prop_Data, "m_iHealth", RoundToNearest(maxhealth)); + SetEntProp(summon, Prop_Data, "m_iMaxHealth", RoundToNearest(maxhealth)); + float flPos[3]; + flPos = pos; + flPos[2] += 300.0; + flPos[0] += GetRandomInt(0,1) ? GetRandomFloat(-200.0, -100.0) : GetRandomFloat(100.0, 200.0); + flPos[1] += GetRandomInt(0,1) ? GetRandomFloat(-200.0, -100.0) : GetRandomFloat(200.0, 200.0); + CClotBody npc = view_as(summon); + npc.SetVelocity({0.0,0.0,0.0}); + PluginBot_Jump(summon, flPos); + } + return 1.0; +} + + + +void Const2Modifs_Explosive_Start(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + //not an npc, ignore. + if(!b_ThisWasAnNpc[victim]) + return; + + SetEntityRenderColor_NpcAll(victim, 2.5, 0.15, 0.15); +} +void Const2Modifs_Explosive_End(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + //not an npc, ignore. + if(!IsValidEntity(victim) || !b_ThisWasAnNpc[victim]) + return; + float DamageDeal = 10000.0; +#if defined ZR + DamageDeal = float(CurrentCash); +#endif + DamageDeal *= 0.25; + if(DamageDeal <= 100.0) + DamageDeal = 100.0; + + b_NpcIsTeamkiller[victim] = true; + Explode_Logic_Custom(DamageDeal, + victim, + victim, + -1, + _, + 350.0, + _, + _, + true, + 99, + false, + 0.01, + _, + BeheadedKamiBoomInternal); + b_NpcIsTeamkiller[victim] = true; + ObjectVintulumBomb npc = view_as(victim); + npc.PlayExplodeDo(true, true); +} + + +void Const2Modifs_Stalker_Start(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + //not an npc, ignore. + if(!b_ThisWasAnNpc[victim]) + return; + + SetEntityRenderColor_NpcAll(victim, 0.0, 0.0, 0.0); + b_StaticNPC[victim] = true; + AddNpcToAliveList(victim, b_StaticNPC[victim] ? 1 : 0); +} +void Disco_Start(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + if(IsValidEntity(Apply_StatusEffect.WearableUse)) + return; + + float flPos[3]; + GetEntPropVector(victim, Prop_Data, "m_vecAbsOrigin", flPos); + + int entity = CreateEntityByName("light_dynamic"); + if(entity != -1) + { + TeleportEntity(entity, flPos, {0.0,0.0,0.0}, NULL_VECTOR); + + DispatchKeyValue(entity, "brightness", "6"); + DispatchKeyValue(entity, "spotlight_radius", "300"); + DispatchKeyValue(entity, "distance", "300"); + DispatchKeyValue(entity, "_light", "255 255 0 255"); + DispatchSpawn(entity); + ActivateEntity(entity); + AcceptEntityInput(entity, "LightOn"); + b_EntityCantBeColoured[entity] = true; + SetParent(victim, entity); + SDKCall_SetLocalOrigin(entity, {0.0,0.0,80.0}); + int ArrayPosition = E_AL_StatusEffects[victim].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); + Apply_StatusEffect.WearableUse = EntIndexToEntRef(entity); + E_AL_StatusEffects[victim].SetArray(ArrayPosition, Apply_StatusEffect); + } + + +} + + + + +static void Disco_Timer(int entity, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + if(Apply_StatusEffect.DataForUse > GetGameTime()) + { + return; + } + if(!IsValidEntity(Apply_StatusEffect.WearableUse)) + return; + + int ArrayPosition = E_AL_StatusEffects[entity].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); + Apply_StatusEffect.DataForUse = GetGameTime() + 0.0; + E_AL_StatusEffects[entity].SetArray(ArrayPosition, Apply_StatusEffect); + int color[4]; + color[0] = GetRandomInt(0,255); + color[1] = GetRandomInt(0,255); + color[2] = GetRandomInt(0,255); + color[3] = 255; + + SetEntityRenderColor(entity, color[0], color[1], color[2], color[3]); + for(int WearableSlot=0; WearableSlot GetGameTime()) + { + return; + } + int ArrayPosition = E_AL_StatusEffects[entity].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); + Apply_StatusEffect.DataForUse = GetGameTime() + 0.5; + E_AL_StatusEffects[entity].SetArray(ArrayPosition, Apply_StatusEffect); + + float DamageDeal = 10000.0; +#if defined ZR + DamageDeal = float(CurrentCash); +#endif + DamageDeal *= 0.005; + Explode_Logic_Custom(DamageDeal, + entity, + entity, + -1, + _, + 100.0, + _, + _, + true, + 99, + false, + 0.01, + _); +} + + +static void Boing_Think_Do(int entity, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + if(Apply_StatusEffect.DataForUse > GetGameTime()) + { + return; + } + int ArrayPosition = E_AL_StatusEffects[entity].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); + Apply_StatusEffect.DataForUse = GetGameTime() + 3.0; + E_AL_StatusEffects[entity].SetArray(ArrayPosition, Apply_StatusEffect); + + float pos[3]; GetEntPropVector(entity, Prop_Data, "m_vecAbsOrigin", pos); + float flPos[3]; + flPos = pos; + flPos[2] += 400.0; + flPos[0] += GetRandomInt(0,1) ? GetRandomFloat(-200.0, -100.0) : GetRandomFloat(100.0, 200.0); + flPos[1] += GetRandomInt(0,1) ? GetRandomFloat(-200.0, -100.0) : GetRandomFloat(200.0, 200.0); + CClotBody npc = view_as(entity); + npc.SetVelocity({0.0,0.0,0.0}) + PluginBot_Jump(entity, flPos); + fl_GravityMulti[entity] = 3.0; + int Rand = GetRandomInt(0, sizeof(BoingSound) - 1); + EmitSoundToAll(BoingSound[Rand], entity, SNDCHAN_AUTO, 80,_,0.85); +} + + +void Knocback_Prefix_TakeDamageAttackerPost(int attacker, int victim, float damage, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect, int damagetype) +{ + if(attacker == victim) + return; + + Custom_Knockback(attacker, victim, 800.0, true); +} + + +#define LEGENDARY_MAXTIME 30.0 +void Legendary_Prefix_Start(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + if(IsValidEntity(Apply_StatusEffect.WearableUse)) + return; + + float flPos[3]; + GetEntPropVector(victim, Prop_Data, "m_vecAbsOrigin", flPos); + int ParticleEffect = ParticleEffectAt_Parent(flPos, "utaunt_poweraura_green_parent", victim, "", {0.0,0.0,0.0}) + if(b_thisNpcIsABoss[victim] || b_thisNpcIsARaid[victim]) + Apply_StatusEffect.DataForUse = GetGameTime() + (LEGENDARY_MAXTIME * 2.0); //Time passed since, after 30 seconds , max power + else + Apply_StatusEffect.DataForUse = GetGameTime() + LEGENDARY_MAXTIME; //Time passed since, after 30 seconds , max power + + int ArrayPosition = E_AL_StatusEffects[victim].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); + Apply_StatusEffect.WearableUse = EntIndexToEntRef(ParticleEffect); + E_AL_StatusEffects[victim].SetArray(ArrayPosition, Apply_StatusEffect); + + +} + + +float Legendary_Prefix_DamageTakenFunc(int attacker, int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect, int damagetype) +{ + float CurrentTime = Apply_StatusEffect.DataForUse; + CurrentTime -= GetGameTime(); + if(CurrentTime <= 0.1) + CurrentTime = 0.1; + + static float MinBuff = 0.5; + static float MaxBuff = 0.85; + float MaxTime = LEGENDARY_MAXTIME; + if(b_thisNpcIsABoss[victim] || b_thisNpcIsARaid[victim]) + MaxTime *= 2.0; + float buffreturn = MinBuff + ((MaxBuff - MinBuff) / (MaxTime / CurrentTime)); + return buffreturn; +} + +float Legendary_Prefix_DamageDealFunc(int attacker, int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect, int damagetype, float basedamage, float DamageBuffExtraScaling) +{ + float CurrentTime = Apply_StatusEffect.DataForUse; + CurrentTime -= GetGameTime(); + if(CurrentTime <= 1.0) + CurrentTime = 1.0; + + static float MinBuff = 2.0; + static float MaxBuff = 0.1; + float MaxTime = LEGENDARY_MAXTIME; + if(b_thisNpcIsABoss[attacker] || b_thisNpcIsARaid[attacker]) + MaxTime *= 2.0; + float buffreturn = MinBuff + ((MaxBuff - MinBuff) / (MaxTime / CurrentTime)); + + float damagereturn = 0.0; + + damagereturn += basedamage * buffreturn; + return damagereturn; +} + +static void Ragebaiter_Think_Do(int entity, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + if(Apply_StatusEffect.DataForUse > GetGameTime()) + { + return; + } + int ArrayPosition = E_AL_StatusEffects[entity].FindValue(Apply_StatusEffect.BuffIndex, E_StatusEffect::BuffIndex); + Apply_StatusEffect.DataForUse = GetGameTime() + GetRandomFloat(10.0, 30.0); + E_AL_StatusEffects[entity].SetArray(ArrayPosition, Apply_StatusEffect); + + + char RageText[255]; + static int MaxEntries; + if(!MaxEntries) + { + MaxEntries++; + Format(RageText, sizeof(RageText), "Rage Prefix Text %i", MaxEntries); + while(TranslationPhraseExists(RageText)) + { + MaxEntries++; + Format(RageText, sizeof(RageText), "Rage Prefix Text %i", MaxEntries); + } + } + Format(RageText, sizeof(RageText), "Rage Prefix Text %i", GetRandomInt(1,MaxEntries- 1)); + + for(int client = 1; client <= MaxClients; client++) + { + if (IsClientInGame(client) && GetTeam(client) == TFTeam_Red) + { + char NamePrefix[255]; + StatusEffects_PrefixName(entity, client, NamePrefix, sizeof(NamePrefix)); + if(!b_NameNoTranslation[entity]) + { + CPrintToChat(client,"{crimson}%s%s {default}: %t",NamePrefix, c_NpcName[entity], RageText); + } + else + { + CPrintToChat(client,"{crimson}%s%t {default}: %t",NamePrefix, c_NpcName[entity], RageText) + } + } + } +} + + + +void SemiHealthy_Start(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + float maxhealth = float(ReturnEntityMaxHealth(victim)); + maxhealth *= 5.0; + SetEntProp(victim, Prop_Data, "m_iMaxHealth", RoundToNearest(maxhealth)); +} +void SemiHealthy_End(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + float maxhealth = float(ReturnEntityMaxHealth(victim)); + maxhealth /= 5.0; + SetEntProp(victim, Prop_Data, "m_iMaxHealth", RoundToNearest(maxhealth)); +} + + +void Const2Modifs_Fat_Start(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + //not an npc, ignore. + if(!b_ThisWasAnNpc[victim]) + return; + + float maxhealth = float(ReturnEntityMaxHealth(victim)); + maxhealth *= 2.0; + SetEntProp(victim, Prop_Data, "m_iHealth", RoundToNearest(maxhealth)); + SetEntProp(victim, Prop_Data, "m_iMaxHealth", RoundToNearest(maxhealth)); + SetEntPropFloat(victim, Prop_Send, "m_flModelScale", GetEntPropFloat(victim, Prop_Send, "m_flModelScale") * 1.35); +} +void Const2Modifs_Fat_End(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + //not an npc, ignore. + if(!IsValidEntity(victim) || !b_ThisWasAnNpc[victim]) + return; + + float maxhealth = float(ReturnEntityMaxHealth(victim)); + maxhealth /= 2.0; + SetEntProp(victim, Prop_Data, "m_iHealth", RoundToNearest(maxhealth)); + SetEntProp(victim, Prop_Data, "m_iMaxHealth", RoundToNearest(maxhealth)); + SetEntPropFloat(victim, Prop_Send, "m_flModelScale", GetEntPropFloat(victim, Prop_Send, "m_flModelScale") * (1.0 / 1.35)); +} + +void Const2Modifs_Modifier_Start(int victim, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) +{ + //not an npc, ignore. + if(!b_ThisWasAnNpc[victim]) + return; + + ZRModifs_GiveRandomPrefix(victim); + ZRModifs_GiveRandomPrefix(victim); } \ No newline at end of file diff --git a/addons/sourcemod/scripting/shared/stocks.sp b/addons/sourcemod/scripting/shared/stocks.sp index bc0560d875..44a277a515 100644 --- a/addons/sourcemod/scripting/shared/stocks.sp +++ b/addons/sourcemod/scripting/shared/stocks.sp @@ -3202,7 +3202,7 @@ void Projectile_DealElementalDamage(int victim, int attacker, float Scale = 1.0) } } -bool OnlyWarnOnceEver = true; +//bool OnlyWarnOnceEver = true; stock void Explode_Logic_Custom(float damage, int client, //To get attributes from and to see what is my enemy! int entity, //Entity that gets forwarded or traced from/Distance checked. @@ -3239,6 +3239,7 @@ int inflictor = 0) explosion_range_dmg_falloff = Attributes_Get(weapon, Attrib_OverrideExplodeDmgRadiusFalloff, EXPLOSION_RANGE_FALLOFF); } #endif +/* if(explosionRadius >= 2100.0) { if(OnlyWarnOnceEver) @@ -3251,6 +3252,7 @@ int inflictor = 0) //at that point it could just be global too. explosionRadius = 2000.0; } +*/ //this should make explosives during raids more usefull. if(!FromBlueNpc) //make sure that there even is any valid npc before we do these huge calcs. { diff --git a/addons/sourcemod/scripting/zombie_riot/dungeons.sp b/addons/sourcemod/scripting/zombie_riot/dungeons.sp index 01eb03d6af..99189ab235 100644 --- a/addons/sourcemod/scripting/zombie_riot/dungeons.sp +++ b/addons/sourcemod/scripting/zombie_riot/dungeons.sp @@ -2466,7 +2466,7 @@ public void ZRModifs_GiveRandomPrefix(int iNpc) bool RetryBuffGiving = false; bool GiveOneGuranteed = true; int MaxHits = 0; - while(GiveOneGuranteed || RetryBuffGiving || GetRandomInt(1,4) == 1) + while(GiveOneGuranteed || RetryBuffGiving || GetRandomInt(1,3) == 1) { MaxHits++; if(MaxHits >= 1000) @@ -2475,7 +2475,7 @@ public void ZRModifs_GiveRandomPrefix(int iNpc) } GiveOneGuranteed = false; RetryBuffGiving = false; - switch(GetRandomInt(1,18)) + switch(GetRandomInt(1,35)) { case 1: { @@ -2614,7 +2614,128 @@ public void ZRModifs_GiveRandomPrefix(int iNpc) Xeno_Resurgance_Enemy(iNpc); } - + case 19: + { + if(HasSpecificBuff(iNpc, "Armoring Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Armoring Prefix", 999999.9); + } + case 20: + { + if(HasSpecificBuff(iNpc, "Motivating Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Motivating Prefix", 999999.9); + } + case 21: + { + if(HasSpecificBuff(iNpc, "Invisible Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Invisible Prefix", 999999.9); + } + case 22: + { + if(HasSpecificBuff(iNpc, "Asexual Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Asexual Prefix", 999999.9); + } + case 23: + { + if(HasSpecificBuff(iNpc, "Glug Infested Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Glug Infested Prefix", 999999.9); + } + case 24: + { + if(HasSpecificBuff(iNpc, "Explosive Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Explosive Prefix", 999999.9); + } + case 25: + { + if(b_thisNpcIsARaid[iNpc] || HasSpecificBuff(iNpc, "Stalker Prefix")) + RetryBuffGiving = true; + else + { + ApplyStatusEffect(iNpc, iNpc, "Stalker Prefix", 999999.9); + ApplyStatusEffect(iNpc, iNpc, "Stalker Prefix Nerf", 999999.9); + } + } + case 26: + { + if(HasSpecificBuff(iNpc, "Disco Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Disco Prefix", 999999.9); + } + case 27: + { + if(HasSpecificBuff(iNpc, "Toxic Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Toxic Prefix", 999999.9); + } + case 28: + { + if(HasSpecificBuff(iNpc, "Boing Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Boing Prefix", 999999.9); + } + case 29: + { + if(HasSpecificBuff(iNpc, "Knockback Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Knockback Prefix", 999999.9); + } + case 30: + { + if(HasSpecificBuff(iNpc, "Loud Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Loud Prefix", 999999.9); + } + case 31: + { + if(HasSpecificBuff(iNpc, "Legendary Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Legendary Prefix", 999999.9); + } + case 32: + { + if(HasSpecificBuff(iNpc, "Ragebaiter Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Ragebaiter Prefix", 999999.9); + } + case 33: + { + if(HasSpecificBuff(iNpc, "Semi Healthy Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Semi Healthy Prefix", 999999.9); + } + case 34: + { + if(HasSpecificBuff(iNpc, "Fat Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Fat Prefix", 999999.9); + } + case 35: + { + if(HasSpecificBuff(iNpc, "Modifier+ Prefix")) + RetryBuffGiving = true; + else + ApplyStatusEffect(iNpc, iNpc, "Modifier+ Prefix", 999999.9); + } } } } diff --git a/addons/sourcemod/scripting/zombie_riot/object/obj_vintulum_bomb.sp b/addons/sourcemod/scripting/zombie_riot/object/obj_vintulum_bomb.sp index 94cd65a53c..eb73560e46 100644 --- a/addons/sourcemod/scripting/zombie_riot/object/obj_vintulum_bomb.sp +++ b/addons/sourcemod/scripting/zombie_riot/object/obj_vintulum_bomb.sp @@ -69,7 +69,7 @@ methodmap ObjectVintulumBomb < ObjectGeneric { EmitSoundToAll(g_ExplosionRightBefore[GetRandomInt(0, sizeof(g_ExplosionRightBefore) - 1)], this.index, SNDCHAN_AUTO, 80, _, 0.8, 100); } - public void PlayExplodeDo(bool alreadydead) + public void PlayExplodeDo(bool alreadydead, bool VisualOnly = false) { EmitSoundToAll(g_ExplosionSound[GetRandomInt(0, sizeof(g_ExplosionSound) - 1)], this.index, SNDCHAN_AUTO, 80, _, 1.0, 100); EmitSoundToAll(g_ExplosionSound[GetRandomInt(0, sizeof(g_ExplosionSound) - 1)], this.index, SNDCHAN_AUTO, 80, _, 1.0, 100); @@ -84,24 +84,27 @@ methodmap ObjectVintulumBomb < ObjectGeneric TE_Particle("grenade_smoke_cycle", pos, NULL_VECTOR, NULL_VECTOR, _, _, _, _, _, _, _, _, _, _, 0.0); - int Owner = GetEntPropEnt(this.index, Prop_Send, "m_hOwnerEntity"); - if(!IsValidClient(Owner)) + if(!VisualOnly) { - return; + int Owner = GetEntPropEnt(this.index, Prop_Send, "m_hOwnerEntity"); + if(!IsValidClient(Owner)) + { + return; + } + float damage = 10.0; + damage *= 30.0; + float attack_speed; + float sentry_range; + attack_speed = 1.0 / Attributes_GetOnPlayer(Owner, 343, true, true); //Sentry attack speed bonus + damage = attack_speed * damage * Attributes_GetOnPlayer(Owner, 287, true, true); //Sentry damage bonus + sentry_range = Attributes_GetOnPlayer(Owner, 344, true, true); //Sentry Range bonus + float AOE_range = 350.0 * sentry_range; + + damage *= 5.0; + //its like 5 mortars at once. + Explode_Logic_Custom(damage, Owner, Owner, -1, pos, AOE_range, 0.75, _, false); + ExpidonsaGroupHeal(Owner, AOE_range, 99, 1.0, 1.0, true, VintulumBombSelf, .LOS = true, .VecDoAt = pos); } - float damage = 10.0; - damage *= 30.0; - float attack_speed; - float sentry_range; - attack_speed = 1.0 / Attributes_GetOnPlayer(Owner, 343, true, true); //Sentry attack speed bonus - damage = attack_speed * damage * Attributes_GetOnPlayer(Owner, 287, true, true); //Sentry damage bonus - sentry_range = Attributes_GetOnPlayer(Owner, 344, true, true); //Sentry Range bonus - float AOE_range = 350.0 * sentry_range; - - damage *= 5.0; - //its like 5 mortars at once. - Explode_Logic_Custom(damage, Owner, Owner, -1, pos, AOE_range, 0.75, _, false); - ExpidonsaGroupHeal(Owner, AOE_range, 99, 1.0, 1.0, true, VintulumBombSelf, .LOS = true, .VecDoAt = pos); int entity = CreateEntityByName("light_dynamic"); if(entity != -1) @@ -119,8 +122,9 @@ methodmap ObjectVintulumBomb < ObjectGeneric CreateTimer(2.0, Timer_RemoveEntity, EntIndexToEntRef(entity), TIMER_FLAG_NO_MAPCHANGE); CreateTimer(0.1, Timer_ReduceLighting, EntIndexToEntRef(entity), TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT); } - if(!alreadydead) - DestroyBuildingDo(this.index); + if(!VisualOnly) + if(!alreadydead) + DestroyBuildingDo(this.index); } property float m_flBombExplodeTill @@ -149,7 +153,6 @@ methodmap ObjectVintulumBomb < ObjectGeneric return npc; } } - static void ClotThink(ObjectVintulumBomb npc) { int Owner = GetEntPropEnt(npc.index, Prop_Send, "m_hOwnerEntity"); diff --git a/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt b/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt index 9183930160..78d0bf8763 100644 --- a/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt +++ b/addons/sourcemod/translations/zombieriot.phrases.status_effects.txt @@ -2631,8 +2631,8 @@ } "The Big Desc" { - "en" "Enlarges by 25%\nIncreases Resistance by 75%" - "ko" "크기가 75% 증가합니다\n저항력이 75% 증가합니다" + "en" "Enlarges by 25%\nIncreases Resistance by 65%" + "ko" "크기가 75% 증가합니다\n저항력이 65% 증가합니다" } "Big" { @@ -2646,8 +2646,8 @@ } "The Strong Desc" { - "en" "Increases Damage by 400%" - "ko" "공격 피해량이 400% 증가합니다" + "en" "Increases Damage by 250%" + "ko" "공격 피해량이 250% 증가합니다" } "Strong" { @@ -2801,8 +2801,8 @@ } "The First Desc" { - "en" "Npc Gains 30% Resistance, 300% Damage, 2x Thinkspeed" - "ko" "NPC의 저항력이 30%, 공격 피해량이 300%, 생각하는 속도가 2배 증가합니다." + "en" "Npc Gains 50% Resistance, 100% Damage, 2x Thinkspeed" + "ko" "NPC의 저항력이 50%, 공격 피해량이 100%, 생각하는 속도가 2배 증가합니다." } "Xeno Infection Buff" { @@ -2826,7 +2826,357 @@ } "Perfected Instinct Desc" { - "en" "Npc Gains 30% Resistance, 300% Damage, 1.5x Thinkspeed, Gains a high chance to dodge attacks, the lower the hp, the higher the chance. On dodge, gain an immensive short speed bonus" - "ko" "NPC 저항력 30%, 피해량 300% 증가. 생각 속도 1.5배. 높은 확률로 공격을 회피, 체력이 감소할 수록 확률 증가. 회피 시 짧은 시간 동안 이동 속도 대폭 증가" + "en" "Npc Gains 40% Resistance, 175% Damage, 1.5x Thinkspeed, Gains a high chance to dodge attacks, the lower the hp, the higher the chance. On dodge, gain an immensive short speed bonus" + "ko" "NPC 저항력 40%, 피해량 175% 증가. 생각 속도 1.5배. 높은 확률로 공격을 회피, 체력이 감소할 수록 확률 증가. 회피 시 짧은 시간 동안 이동 속도 대폭 증가" + } + "Motivating Prefix" + { + "en" "Motivating Prefix" + } + "Motivating" + { + "en" "Motivating" + } + "Motivating Prefix Desc" + { + "en" "Buffs allies with Warcry around itself." + } + "Invisible Prefix" + { + "en" "Invisible Prefix" + } + "Invisible" + { + "en" "Invisible" + } + "Invisible Prefix Desc" + { + "en" "Enemies get invisible at far ranges and get stronger." + } + + "Asexual Prefix" + { + "en" "Asexual Prefix" + } + "Asexual" + { + "en" "Asexual" + } + "Asexual Prefix Desc" + { + "en" "On Death, Splits up into 2 that guranteed get modifiers" + } + "Legendary Prefix" + { + "en" "Legendary Prefix" + } + "Legendary" + { + "en" "Legendary" + } + "Legendary Prefix Desc" + { + "en" "Gets stronger overtime, at 30 seconds gains max power!" + } + "Glug Infested Prefix" + { + "en" "Glug Infested Prefix" + } + "Glug Infested" + { + "en" "Glug Infested" + } + "Glug Infested Desc" + { + "en" "When hurt, everyso often, spawns a glug on their side" + } + "Armoring Prefix" + { + "en" "Armoring Prefix" + } + "Armoring" + { + "en" "Armoring" + } + "Armoring Prefix Desc" + { + "en" "Regenerate armor 20% of max health every 3 seconds" + } + "Explosive Prefix" + { + "en" "Explosive Prefix" + } + "Explosive" + { + "en" "Explosive" + } + "Explosive Prefix Desc" + { + "en" "When dead, explodes into a nuke, damaging everyone" + } + "Stalker Prefix" + { + "en" "Stalker Prefix" + } + "Stalker" + { + "en" "Stalker" + } + "Stalker Prefix Desc" + { + "en" "Bypasses waves and gains insane buffs but much slower walkspeed" + } + "Disco Prefix" + { + "en" "Disco Prefix" + } + "Disco" + { + "en" "Disco" + } + "Disco Prefix Desc" + { + "en" "Flickers lights, partey!!!" + } + "Toxic Prefix" + { + "en" "Toxic Prefix" + } + "Toxic" + { + "en" "Toxic" + } + "Toxic Prefix Desc" + { + "en" "Deals damage to enemies around itself" + } + "Boing Prefix" + { + "en" "Boing Prefix" + } + "Boing" + { + "en" "Boing" + } + "Boing Prefix Desc" + { + "en" "Bounces around like a trampoline" + } + "Knockback Prefix" + { + "en" "Knockback Prefix" + } + "Knockback" + { + "en" "Knockback" + } + "Knockback Prefix Desc" + { + "en" "Enemies on dealin damage recieve knockback" + } + "Loud Prefix" + { + "en" "Loud Prefix" + } + "Loud" + { + "en" "Loud" + } + "Loud Prefix Desc" + { + "en" "Makes all sounds you create 3x as loud" + } + "Ragebaiter Prefix" + { + "en" "Ragebaiter Prefix" + } + "Ragebaiter" + { + "en" "Ragebaiter" + } + "Ragebaiter Prefix Desc" + { + "en" "Makes you forcefully type nasty stuff in chat" + } + "Rage Prefix Text 1" + { + "en" "I WILL KILL YOU" + } + "Rage Prefix Text 2" + { + "en" "ok." + } + "Rage Prefix Text 3" + { + "en" "Youre welcome" + } + "Rage Prefix Text 4" + { + "en" "My favorite toast is your BLOOD" + } + "Rage Prefix Text 5" + { + "en" "FUCKING ASSHOLE" + } + "Rage Prefix Text 6" + { + "en" "I HATE EVERYTHING" + } + "Rage Prefix Text 7" + { + "en" "RAAAAAAAAAAAAAAAAAAAAHHHHHH!!!!!!!!!!" + } + "Rage Prefix Text 8" + { + "en" "RFHSGDGTWF ZJHEHMTZMBHJTEMNVUETH" + } + "Rage Prefix Text 9" + { + "en" "Owned BITCH" + } + "Rage Prefix Text 10" + { + "en" "Let me touch you boy" + } + "Rage Prefix Text 11" + { + "en" "My hand + your head = Match made in heaven" + } + "Rage Prefix Text 12" + { + "en" "Guess what? Chicken butt" + } + "Rage Prefix Text 13" + { + "en" "This is getting pretty serious." + } + "Rage Prefix Text 14" + { + "en" "These hands are rated E for everyone" + } + "Rage Prefix Text 15" + { + "en" "I just took a shit" + } + "Rage Prefix Text 16" + { + "en" "I found out i have work tomorrow, day ruined" + } + "Rage Prefix Text 17" + { + "en" "I can't win with these kings gg ." + //This joke only works in english, for your own languge, make some other national joke + } + "Rage Prefix Text 18" + { + "en" "Just browsed 4chan, it was very good, my head enlightened." + } + "Rage Prefix Text 19" + { + "en" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + "Rage Prefix Text 20" + { + "en" ":trolley:" + } + "Rage Prefix Text 21" + { + "en" "bruh" + } + "Rage Prefix Text 22" + { + "en" "i hope no one looks at my plans while im sleeping" + } + "Rage Prefix Text 23" + { + "en" "HOO HAA" + } + "Rage Prefix Text 24" + { + "en" "Feeling like snorting cocain rn ngl fr fr" + } + "Rage Prefix Text 25" + { + "en" "I played minecraft" + } + "Rage Prefix Text 26" + { + "en" "I am like, super evil, dude, just kidding go kill yourself." + } + "Rage Prefix Text 27" + { + "en" "I hope youre lactose intollerant cus im about to milk someone." + } + "Rage Prefix Text 28" + { + "en" "Old times interitus is my bitch" + } + "Rage Prefix Text 29" + { + "en" "☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺☻☺" + } + "Rage Prefix Text 30" + { + "en" "♅ is looking mighty today. Let me grab that." + } + "Rage Prefix Text 31" + { + "en" "If you think liking a guy is gay, youre wrong, imagine liking a woman and putting up with their bullshit. now thats gay." + } + "Rage Prefix Text 32" + { + "en" "Niko sucks" + } + "Rage Prefix Text 33" + { + "en" "Zombie riot is full of SHIT!!" + } + "Rage Prefix Text 34" + { + "en" "Shoutout to my homies, they up in this bitch" + } + "Rage Prefix Text 35" + { + "en" "wat u want bitch" + } + "Rage Prefix Text 36" + { + "en" "You ever had gay thoughts? Act on them." + } + "Semi Healthy Prefix" + { + "en" "Semi Healthy Prefix" + } + "Semi Healthy" + { + "en" "Semi Healthy" + } + "Semi Healthy Prefix Desc" + { + "en" "Increases Max health by 5x, does not immedietly heal" + } + "Fat Prefix" + { + "en" "Fat Prefix" + } + "Fat" + { + "en" "Fat" + } + "Fat Prefix Desc" + { + "en" "Increases health by 2x, increases size by 1.35x, slows down npcs by 1.25x" + } + "Modifier+ Prefix" + { + "en" "Modifier+ Prefix" + } + "Modifier+" + { + "en" "Modifier+" + } + "Modifier+ Prefix Desc" + { + "en" "Gives 2 modifier chances to get additional chances" } } diff --git a/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt b/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt index 79d8f2aef5..1029aa1bed 100644 --- a/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt +++ b/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt @@ -5900,6 +5900,10 @@ { "en" "Chemical Specialist" } + "Chemical Spreader" + { + "en" "Chemical Spreader" + } "Giant Armored Medibot" { "en" "Giant Armored Medibot" From 1e1b8e7b5162308b25d2991c652a40419ef6e05d Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Tue, 10 Feb 2026 01:01:36 +0100 Subject: [PATCH 20/24] change up --- .../sourcemod/scripting/shared/status_effects.sp | 16 +++++++++------- .../sourcemod/scripting/zombie_riot/dungeons.sp | 12 ++++++++++-- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/addons/sourcemod/scripting/shared/status_effects.sp b/addons/sourcemod/scripting/shared/status_effects.sp index b1ff0cccd4..088b9323f9 100644 --- a/addons/sourcemod/scripting/shared/status_effects.sp +++ b/addons/sourcemod/scripting/shared/status_effects.sp @@ -7526,7 +7526,7 @@ void StatusEffects_Construct2_EnemyModifs() strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Stalker"); //-1.0 means unused - data.DamageTakenMulti = 0.01; + data.DamageTakenMulti = -1.0; data.DamageDealMulti = 5.0; data.MovementspeedModif = -1.0; data.AttackspeedBuff = -1.0; @@ -7544,7 +7544,7 @@ void StatusEffects_Construct2_EnemyModifs() //-1.0 means unused data.DamageTakenMulti = -1.0; data.DamageDealMulti = -1.0; - data.MovementspeedModif = 0.75; + data.MovementspeedModif = 0.85; data.AttackspeedBuff = -1.0; data.Positive = false; data.ElementalLogic = true; @@ -8044,12 +8044,10 @@ static void Const2_Armoring_Timer(int entity, StatusEffect Apply_MasterStatusEff float maxhealth = float(ReturnEntityMaxHealth(entity)); if(b_thisNpcIsARaid[entity] || b_thisNpcIsABoss[entity]) - maxhealth *= 0.01; - GrantEntityArmor(entity, false, 1.0, 0.25, 0, maxhealth / 5.0); + maxhealth *= 0.025; + GrantEntityArmor(entity, false, 1.0, 0.25, 0, maxhealth / 4.0); } - - static void Const2_Laggy_Timer(int entity, StatusEffect Apply_MasterStatusEffect, E_StatusEffect Apply_StatusEffect) { if(Apply_StatusEffect.DataForUse > GetGameTime()) @@ -8511,6 +8509,10 @@ void Const2Modifs_Stalker_Start(int victim, StatusEffect Apply_MasterStatusEffec if(!b_ThisWasAnNpc[victim]) return; + float maxhealth = float(ReturnEntityMaxHealth(victim)); + maxhealth *= 100.0; + SetEntProp(victim, Prop_Data, "m_iHealth", RoundToNearest(maxhealth)); + SetEntProp(victim, Prop_Data, "m_iMaxHealth", RoundToNearest(maxhealth)); SetEntityRenderColor_NpcAll(victim, 0.0, 0.0, 0.0); b_StaticNPC[victim] = true; AddNpcToAliveList(victim, b_StaticNPC[victim] ? 1 : 0); @@ -8621,7 +8623,7 @@ static void Toxic_Think_Do(int entity, StatusEffect Apply_MasterStatusEffect, E_ entity, -1, _, - 100.0, + 200.0, _, _, true, diff --git a/addons/sourcemod/scripting/zombie_riot/dungeons.sp b/addons/sourcemod/scripting/zombie_riot/dungeons.sp index 99189ab235..27ccec7b76 100644 --- a/addons/sourcemod/scripting/zombie_riot/dungeons.sp +++ b/addons/sourcemod/scripting/zombie_riot/dungeons.sp @@ -2662,8 +2662,16 @@ public void ZRModifs_GiveRandomPrefix(int iNpc) RetryBuffGiving = true; else { - ApplyStatusEffect(iNpc, iNpc, "Stalker Prefix", 999999.9); - ApplyStatusEffect(iNpc, iNpc, "Stalker Prefix Nerf", 999999.9); + if(GetRandomInt(1,4) == 1) + { + ApplyStatusEffect(iNpc, iNpc, "Stalker Prefix", 999999.9); + ApplyStatusEffect(iNpc, iNpc, "Stalker Prefix Nerf", 999999.9); + } + else + { + //make it really really rare + RetryBuffGiving = true; + } } } case 26: From 3b38bf89be87d334c9ffcb0ec19df4df84e7271d Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Tue, 10 Feb 2026 01:04:13 +0100 Subject: [PATCH 21/24] save --- addons/sourcemod/scripting/zombie_riot/dungeons.sp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/sourcemod/scripting/zombie_riot/dungeons.sp b/addons/sourcemod/scripting/zombie_riot/dungeons.sp index 27ccec7b76..f0720b29e7 100644 --- a/addons/sourcemod/scripting/zombie_riot/dungeons.sp +++ b/addons/sourcemod/scripting/zombie_riot/dungeons.sp @@ -2576,7 +2576,7 @@ public void ZRModifs_GiveRandomPrefix(int iNpc) } case 15: { - if(b_thisNpcIsARaid[iNpc] || Elemental_DamageRatio(iNpc, Element_Warped) > 0.0) + if(RaidBossActive == EntIndexToEntRef(iNpc) || b_thisNpcIsARaid[iNpc] || Elemental_DamageRatio(iNpc, Element_Warped) > 0.0) { RetryBuffGiving = true; } @@ -2658,7 +2658,7 @@ public void ZRModifs_GiveRandomPrefix(int iNpc) } case 25: { - if(b_thisNpcIsARaid[iNpc] || HasSpecificBuff(iNpc, "Stalker Prefix")) + if(RaidBossActive == EntIndexToEntRef(iNpc) || b_thisNpcIsARaid[iNpc] || HasSpecificBuff(iNpc, "Stalker Prefix")) RetryBuffGiving = true; else { From 624508ecb24c3792e854895fc2e30e08ab76d0f3 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Tue, 10 Feb 2026 01:07:13 +0100 Subject: [PATCH 22/24] save --- addons/sourcemod/scripting/shared/status_effects.sp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/sourcemod/scripting/shared/status_effects.sp b/addons/sourcemod/scripting/shared/status_effects.sp index 088b9323f9..f9a379b633 100644 --- a/addons/sourcemod/scripting/shared/status_effects.sp +++ b/addons/sourcemod/scripting/shared/status_effects.sp @@ -7917,7 +7917,7 @@ static void Const2_Sprayer_Timer(int entity, StatusEffect Apply_MasterStatusEffe #if defined ZR DamageDeal = float(CurrentCash); #endif - DamageDeal *= 0.005; + DamageDeal *= 0.0025; if(DamageDeal <= 50.0) DamageDeal = 50.0; @@ -7941,7 +7941,7 @@ static void Const2_Sprayer_Timer(int entity, StatusEffect Apply_MasterStatusEffe Initiate_HomingProjectile(projectile, projectile, 90.0, // float lockonAngleMax, - 13.0, //float homingaSec, + 10.0, //float homingaSec, false, // bool LockOnlyOnce, true, // bool changeAngles, angles); // float AnglesInitiate[3]); From 750a4abbdc87b4418749132eba51e751b9c0fcdb Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Tue, 10 Feb 2026 01:53:26 +0100 Subject: [PATCH 23/24] save --- .../scripting/shared/status_effects.sp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/addons/sourcemod/scripting/shared/status_effects.sp b/addons/sourcemod/scripting/shared/status_effects.sp index f9a379b633..b994136335 100644 --- a/addons/sourcemod/scripting/shared/status_effects.sp +++ b/addons/sourcemod/scripting/shared/status_effects.sp @@ -7089,8 +7089,8 @@ void StatusEffects_Construct2_EnemyModifs() //-1.0 means unused data.DamageTakenMulti = -1.0; data.DamageDealMulti = -1.0; - data.MovementspeedModif = 1.15; - data.AttackspeedBuff = (1.0 / 3.0); + data.MovementspeedModif = 1.1; + data.AttackspeedBuff = (1.0 / 2.0); data.Positive = true; data.ShouldScaleWithPlayerCount = false; data.OnBuffStarted = Const2Modifs_Haste_Start; @@ -7103,7 +7103,7 @@ void StatusEffects_Construct2_EnemyModifs() strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Big"); //-1.0 means unused - data.DamageTakenMulti = 0.35; + data.DamageTakenMulti = 0.5; data.DamageDealMulti = -1.0; data.MovementspeedModif = -1.0; data.AttackspeedBuff = -1.0; @@ -7119,7 +7119,7 @@ void StatusEffects_Construct2_EnemyModifs() strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Strong"); //-1.0 means unused data.DamageTakenMulti = -1.0; - data.DamageDealMulti = 2.5; + data.DamageDealMulti = 1.75; data.MovementspeedModif = -1.0; data.AttackspeedBuff = -1.0; data.Positive = true; @@ -7219,7 +7219,7 @@ void StatusEffects_Construct2_EnemyModifs() //-1.0 means unused data.DamageTakenMulti = -1.0; data.DamageDealMulti = -1.0; - data.MovementspeedModif = -1.0; + data.MovementspeedModif = -1.0; data.AttackspeedBuff = -1.0; data.Positive = true; data.ShouldScaleWithPlayerCount = false; @@ -7361,10 +7361,10 @@ void StatusEffects_Construct2_EnemyModifs() strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), "TF"); //dont display above head, so empty strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "The First"); //-1.0 means unused - data.DamageTakenMulti = 0.5; - data.DamageDealMulti = 1.0; + data.DamageTakenMulti = 0.6; + data.DamageDealMulti = 0.7; data.MovementspeedModif = -1.0; - data.AttackspeedBuff = (1.0 / 2.0); + data.AttackspeedBuff = (1.0 / 1.5); data.Positive = true; data.ShouldScaleWithPlayerCount = false; data.OnBuffStarted = INVALID_FUNCTION; @@ -7410,8 +7410,8 @@ void StatusEffects_Construct2_EnemyModifs() strcopy(data.AboveEnemyDisplay, sizeof(data.AboveEnemyDisplay), ""); //dont display above head, so empty strcopy(data.PrefixEnemyName, sizeof(data.PrefixEnemyName), "Perfected Instinct"); //-1.0 means unused - data.DamageTakenMulti = 0.6; - data.DamageDealMulti = 1.75; + data.DamageTakenMulti = 0.75; + data.DamageDealMulti = 0.4; data.MovementspeedModif = -1.0; data.AttackspeedBuff = (1.0 / 1.5); data.Positive = true; @@ -7429,7 +7429,7 @@ void StatusEffects_Construct2_EnemyModifs() //-1.0 means unused data.DamageTakenMulti = -1.0; data.DamageDealMulti = -1.0; - data.MovementspeedModif = 4.0; + data.MovementspeedModif = 3.0; data.AttackspeedBuff = -1.0; data.Positive = true; data.ShouldScaleWithPlayerCount = false; From 96b39b02c84ad2908012d72eec7074e3738c4c14 Mon Sep 17 00:00:00 2001 From: Artvin <76885107+artvin01@users.noreply.github.com> Date: Tue, 10 Feb 2026 01:55:26 +0100 Subject: [PATCH 24/24] save --- addons/sourcemod/scripting/shared/status_effects.sp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/sourcemod/scripting/shared/status_effects.sp b/addons/sourcemod/scripting/shared/status_effects.sp index b994136335..d3a2046e5c 100644 --- a/addons/sourcemod/scripting/shared/status_effects.sp +++ b/addons/sourcemod/scripting/shared/status_effects.sp @@ -8374,8 +8374,8 @@ void Const2Modifs_Asexual_End(int victim, StatusEffect Apply_MasterStatusEffect, fl_Extra_Speed[summon] = fl_Extra_Speed[victim]; fl_Extra_RangedArmor[summon] = fl_Extra_RangedArmor[victim]; fl_Extra_MeleeArmor[summon] = fl_Extra_MeleeArmor[victim]; - SetEntProp(victim, Prop_Data, "m_iHealth", RoundToNearest(maxhealth)); - SetEntProp(victim, Prop_Data, "m_iMaxHealth", RoundToNearest(maxhealth)); + SetEntProp(summon, Prop_Data, "m_iHealth", RoundToNearest(maxhealth)); + SetEntProp(summon, Prop_Data, "m_iMaxHealth", RoundToNearest(maxhealth)); float flPos[3]; flPos = pos; flPos[2] += 300.0;