diff --git a/addons/sourcemod/configs/zombie_riot/fast_zs.cfg b/addons/sourcemod/configs/zombie_riot/fast_zs.cfg index 42c5412b34..39f062d8ed 100644 --- a/addons/sourcemod/configs/zombie_riot/fast_zs.cfg +++ b/addons/sourcemod/configs/zombie_riot/fast_zs.cfg @@ -10,6 +10,7 @@ "auto_raid_cash" "1" "cash" "700" "fakemaxwaves" "40" + "resourceregen" "1.2" "relay_send_start" "zr_waves_zombie_survival" "music_setup" @@ -73,7 +74,7 @@ } "0.0" { - "count" "9" + "count" "6" "plugin" "npc_zs_fast_zombie" } } @@ -117,27 +118,27 @@ "1.0" { - "count" "5" + "count" "4" "plugin" "npc_zs_headcrab" } "1.0" { - "count" "5" + "count" "4" "plugin" "npc_zs_ghoul" } "1.0" { - "count" "3" + "count" "4" "plugin" "npc_zs_gore_blaster" } "1.0" { - "count" "7" + "count" "4" "plugin" "npc_zs_zombie" } "0.0" { - "count" "6" + "count" "4" "plugin" "npc_zs_fast_zombie" } } @@ -151,7 +152,7 @@ } "1.0" { - "count" "9" + "count" "5" "health" "800" "plugin" "npc_zs_medic_healer" } @@ -169,7 +170,7 @@ } "1.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_shadow_walker" } "0.0" @@ -324,23 +325,22 @@ "count" "2" "health" "15000" "is_boss" "1" - "extra_damage" "1.25" "plugin" "npc_random_zombie" } - "1.0" + "5.0" { - "count" "6" - "plugin" "npc_zs_bloated_zombie" + "count" "5" + "plugin" "npc_zs_zmain_poisonzombie" } - "1.0" + "5.0" { - "count" "15" - "plugin" "npc_zs_runner" + "count" "5" + "plugin" "npc_zs_zmain_headcrabzombie" } "0.0" { - "count" "15" - "plugin" "npc_zs_fast_zombie" + "count" "10" + "plugin" "npc_zs_zmain_headcrab" } } "10" @@ -441,7 +441,7 @@ } "0.0" //The Trojan Horse { - "count" "10" + "count" "5" "plugin" "npc_zs_zombie" } } @@ -467,7 +467,7 @@ } "1.0" { - "count" "2" + "count" "5" "plugin" "npc_zs_poisonheadcrab_zombie" } "0.0" @@ -486,21 +486,21 @@ } "1.0" { - "count" "10" + "count" "5" "health" "3200" "extra_damage" "2" "plugin" "npc_zs_skeleton" } "1.0" { - "count" "10" + "count" "5" "health" "3200" "extra_damage" "2" "plugin" "npc_zs_shadow_walker" } "1.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_poisonheadcrab_zombie" } @@ -530,8 +530,8 @@ "count" "1" "health" "30000" "is_boss" "1" - "extra_damage" "2.0" - "plugin" "npc_zs_amplification" + "plugin" "npc_random_zombie" + "cash" "0" } "20.0" { @@ -541,7 +541,7 @@ } "0.0" { - "count" "10" + "count" "8" "plugin" "npc_zs_fastheadcrab_zombie" } } @@ -558,7 +558,7 @@ } "5.0" { - "count" "10" + "count" "8" "health" "3200" "extra_damage" "2" "plugin" "npc_zs_runner" @@ -669,7 +669,6 @@ "count" "3" "health" "30000" "is_boss" "1" - "extra_damage" "2.0" "plugin" "npc_random_zombie" "cash" "0" } @@ -681,8 +680,7 @@ "1.0" { "count" "2" - "health" "3200" - "plugin" "npc_zs_medic_healer" + "plugin" "npc_zs_vile_bloated_zombie" } "30.0" { @@ -724,10 +722,7 @@ "5.0" //GREGGORY { "count" "2" - "health" "30000" - "is_boss" "1" - "extra_damage" "2.0" - "plugin" "npc_zs_butcher" + "plugin" "npc_zs_poisonheadcrab_zombie" } "5.0" { @@ -737,12 +732,12 @@ } "1.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_headcrabzombie" } "1.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_fastheadcrab_zombie" } "0.0" @@ -771,39 +766,20 @@ "plugin" "npc_random_zombie" "cash" "0" } - "30.0" - { - "count" "10" - "plugin" "npc_zs_elder_ghoul" - } - "1.0" - { - "count" "5" - "plugin" "npc_zs_spitter" - } - "1.0" - { - "count" "3" - "plugin" "npc_zs_headcrabzombie" - } - "1.0" + "5.0" { "count" "5" - "plugin" "npc_zs_fastheadcrab_zombie" + "plugin" "npc_zs_zmain_poisonzombie" } - "1.0" + "5.0" { "count" "5" - "health" "3200" - "extra_damage" "2" - "plugin" "npc_zs_shadow_walker" + "plugin" "npc_zs_zmain_headcrabzombie" } "0.0" { - "count" "5" - "health" "3200" - "extra_damage" "2" - "plugin" "npc_zs_skeleton" + "count" "10" + "plugin" "npc_zs_zmain_headcrab" } } "20" @@ -865,7 +841,6 @@ "count" "3" "health" "30000" "is_boss" "1" - "extra_damage" "2.0" "plugin" "npc_random_zombie" "cash" "0" } @@ -892,7 +867,7 @@ } "1.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_headcrabzombie" } "1.0" @@ -903,21 +878,21 @@ } "1.0" { - "count" "10" + "count" "5" "health" "3200" "extra_damage" "2" "plugin" "npc_zs_skeleton" } "1.0" { - "count" "10" + "count" "5" "health" "3200" "extra_damage" "2" "plugin" "npc_zs_shadow_walker" } "1.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_spitter" } "1.0" @@ -957,7 +932,7 @@ } "15.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_huntsman" } "1.0" @@ -967,7 +942,7 @@ } "0.0" { - "count" "10" + "count" "8" "plugin" "npc_zs_kamikaze_demo" } } @@ -982,7 +957,7 @@ } "10.0" { - "count" "12" + "count" "6" "plugin" "npc_zs_zombie_heavy" } "1.0" @@ -992,9 +967,14 @@ } "5.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_kamikaze_demo" } + "5.0" + { + "count" "2" + "plugin" "npc_zs_hmo" + } "1.0" { "count" "8" @@ -1022,7 +1002,7 @@ } "5.0" { - "count" "20" + "count" "8" "plugin" "npc_zs_zombie_soldier" } "10.0" //GREGGORY @@ -1037,7 +1017,7 @@ } "0.0" { - "count" "20" + "count" "8" "plugin" "npc_zs_zombie_spy" } } @@ -1050,9 +1030,8 @@ "1.0" { "count" "3" - "health" "50000" + "health" "60000" "is_boss" "1" - "extra_damage" "2.0" "plugin" "npc_random_zombie" "cash" "0" } @@ -1063,8 +1042,8 @@ } "5.0" { - "count" "8" - "plugin" "npc_zs_zombie_spy" + "count" "3" + "plugin" "npc_zs_hmo" } "1.0" { @@ -1078,7 +1057,7 @@ } "1.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_zombie_heavy" } "1.0" @@ -1089,7 +1068,7 @@ "0.0" { "count" "2" - "plugin" "npc_zs_kamikaze_demo" //3 being the 3rd stage of alt waves. + "plugin" "npc_infected_tomislav_main" //3 being the 3rd stage of alt waves. } } "25" @@ -1097,7 +1076,7 @@ "cash" "1500" "5.0" { - "count" "15" + "count" "6" "plugin" "npc_zs_zombie_scout" } "5.0" @@ -1108,12 +1087,12 @@ } "10.0" { - "count" "20" + "count" "7" "plugin" "npc_zs_kamikaze_demo" } "5.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_zombie_soldier" } "30.0" @@ -1129,7 +1108,7 @@ "1.0" { "count" "5" - "plugin" "npc_zs_medic_healer" //3 being the 3rd stage of alt waves. + "plugin" "npc_infected_tomislav_main" //3 being the 3rd stage of alt waves. } "0.0" { @@ -1143,7 +1122,7 @@ "10.0" { - "count" "20" + "count" "8" "plugin" "npc_zs_zombie_scout" } "1.0" @@ -1159,7 +1138,7 @@ "30.0" //Overlord { "count" "2" - "plugin" "npc_zs_kamikaze_demo" + "plugin" "npc_zs_hmo" } "1.0" { @@ -1173,7 +1152,7 @@ } "15.0" { - "count" "14" + "count" "7" "plugin" "npc_zs_zombie_heavy" } "0.0" @@ -1191,7 +1170,7 @@ "5.0" { - "count" "10" + "count" "8" "plugin" "npc_zs_zombie_soldier_pickaxe" } "5.0" @@ -1201,7 +1180,7 @@ } "5.0" { - "count" "20" + "count" "8" "plugin" "npc_zs_kamikaze_demo" } "1.0" @@ -1211,12 +1190,12 @@ } "5.0" { - "count" "15" + "count" "7" "plugin" "npc_zs_zombie_engineer" } "0.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_zombie_spy" //3 being the 3rd stage of alt waves. } } @@ -1236,7 +1215,7 @@ } "15.0" { - "count" "20" + "count" "8" "plugin" "npc_zs_kamikaze_demo" } "1.0" @@ -1246,7 +1225,7 @@ } "1.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_zombie_soldier" //3 being the 3rd stage of alt waves. } "0.0" @@ -1268,44 +1247,32 @@ "author" "it's from Zombie Survival" "volume" "0.7" } - - "1.0" - { - "count" "10" - "health" "9200" - "plugin" "npc_zs_poisonheadcrab_zombie" - } - "1.0" //GREGGORY - { - "count" "4" - "plugin" "npc_zombine" - } - "15.0" //Overlord - { - "count" "1" - "health" "25000" - "plugin" "npc_zmain_poisonzombie" - } "1.0" { - "count" "14" - "plugin" "npc_zs_medic_healer" //3 being the 3rd stage of alt waves. + "count" "3" + "health" "60000" + "is_boss" "1" + "plugin" "npc_random_zombie" + "cash" "0" } "5.0" { "count" "5" - "plugin" "npc_zs_zombie_heavy" + "health" "50000" + "plugin" "npc_zs_zmain_poisonzombie" } - "1.0" + "5.0" { - "count" "10" - "plugin" "npc_zs_zombie_demoknight" //alt ddt. + "count" "5" + "health" "25000" + "plugin" "npc_zs_zmain_headcrabzombie" } "0.0" { "count" "10" - "plugin" "npc_zs_zombie_spy" //alt soldier - } + "health" "5000" + "plugin" "npc_zs_zmain_headcrab" + } } "30" { @@ -1325,7 +1292,7 @@ "grigori_refresh_store" "1" "map_setup_fake" "1" - "5.0" + "10.0" { "count" "0" "health" "1000000" @@ -1334,25 +1301,24 @@ "is_health_scaling" "1" "plugin" "npc_zs_sphynx" } - "1.0" + "5.0" { - "count" "20" + "count" "7" "plugin" "npc_zs_kamikaze_demo" } "1.0" { - "count" "12" - "plugin" "npc_zs_zombie_heavy" + "count" "6" + "plugin" "npc_zs_zombie_scout" } "1.0" { - "count" "10" - "health" "7500" + "count" "5" "plugin" "npc_zs_huntsman" } "1.0" { - "count" "14" + "count" "7" "plugin" "npc_zs_zombie_soldier_pickaxe" } "10.0" @@ -1363,12 +1329,12 @@ } "1.0" { - "count" "20" + "count" "6" "plugin" "npc_zs_zombie_demoknight" } "1.0" { - "count" "20" + "count" "6" "plugin" "npc_zs_medic_healer" //3 being the 3rd stage of alt waves. } "1.0" @@ -1382,20 +1348,31 @@ "health" "300000" "is_boss" "1" "plugin" "npc_random_zombie" + "cash" "0" } "1.0" { - "count" "12" - "plugin" "npc_zs_zombie_scout" + "count" "2" + "plugin" "npc_zs_hmo" + } + "1.0" + { + "count" "6" + "plugin" "npc_zs_zombie_heavy" } "1.0" { - "count" "12" + "count" "7" "plugin" "npc_zs_zombie_engineer" } + "1.0" + { + "count" "7" + "plugin" "npc_infected_tomislav_main" + } "0.0" { - "count" "12" + "count" "7" "plugin" "npc_zs_zombie_soldier" } } @@ -1406,17 +1383,17 @@ "1.0" { - "count" "20" + "count" "7" "plugin" "npc_zs_eradicator" } "1.0" { - "count" "14" + "count" "7" "plugin" "npc_zs_vile_poisonheadcrab_zombie" } "1.0" { - "count" "14" + "count" "7" "plugin" "npc_zs_firefighter" } "1.0" @@ -1451,7 +1428,12 @@ } "1.0" { - "count" "20" + "count" "6" + "plugin" "npc_zs_manhattan_parrot" + } + "1.0" + { + "count" "10" "plugin" "npc_zs_sniper" } "0.0" @@ -1463,20 +1445,27 @@ "33" { "cash" "1850" - "1.0" { - "count" "20" + "count" "1" + "health" "112500" + "is_boss" "1" + "plugin" "npc_random_zombie" + "cash" "0" + } + "1.0" + { + "count" "5" "plugin" "npc_zs_eradicator" } "1.0" { - "count" "14" + "count" "7" "plugin" "npc_zs_zombie_breadmonster" } "1.0" { - "count" "14" + "count" "7" "plugin" "npc_zs_cleaner" } "1.0" @@ -1517,17 +1506,22 @@ } "1.0" { - "count" "20" + "count" "8" + "plugin" "npc_zs_mlsm" + } + "1.0" + { + "count" "8" "plugin" "npc_zs_eradicator" } "1.0" { - "count" "14" + "count" "7" "plugin" "npc_zs_zombie_breadmonster" } "1.0" { - "count" "14" + "count" "8" "plugin" "npc_zs_cleaner" } "1.0" @@ -1549,8 +1543,8 @@ "count" "1" "health" "112500" "is_boss" "1" - "extra_damage" "3" "plugin" "npc_random_zombie" + "cash" "0" } "1.0" { @@ -1560,30 +1554,33 @@ } "1.0" { - "count" "20" + "count" "8" "plugin" "npc_zs_eradicator" } "1.0" { - "count" "14" + "count" "8" "plugin" "npc_zs_sam" } "1.0" { - "count" "14" + "count" "6" "plugin" "npc_zs_cleaner" } "1.0" { "count" "7" - "health" "30000" - "plugin" "npc_zs_zombie_sniper_jarate" + "plugin" "npc_zs_ihbc" + } + "1.0" + { + "count" "5" + "plugin" "npc_zs_combine_soldier_elite" } "0.0" { - "count" "7" - "health" "35000" - "plugin" "npc_zs_zombie_demoknight" + "count" "5" + "plugin" "npc_zs_mlsm" } } "36" @@ -1591,22 +1588,27 @@ "cash" "3000" "1.0" { - "count" "10" + "count" "7" "plugin" "npc_zs_zombie_breadmonster" } "1.0" { - "count" "20" + "count" "5" + "plugin" "npc_zs_mlsm" + } + "1.0" + { + "count" "7" "plugin" "npc_zs_zombie_fatspy" } "1.0" { - "count" "14" + "count" "8" "plugin" "npc_zs_zombie_fatscout" } "1.0" { - "count" "14" + "count" "8" "plugin" "npc_zs_medic_main" } "1.0" @@ -1626,42 +1628,67 @@ "grigori_refresh_store" "1" "map_setup_fake" "1" - "1.0" { - "count" "10" + "count" "2" + "health" "112500" + "is_boss" "1" + "plugin" "npc_random_zombie" + "cash" "0" + } + "1.0" + { + "count" "5" "plugin" "npc_zs_ihbc" } "1.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_sniper" } "1.0" { - "count" "14" + "count" "5" "plugin" "npc_zs_eradicator" } "1.0" { - "count" "14" + "count" "5" "plugin" "npc_zs_medic_main" } "1.0" { - "count" "7" - "plugin" "npc_zs_cleaner" + "count" "5" + "plugin" "npc_zs_mlsm" } "0.0" { "count" "7" - "health" "35000" - "plugin" "npc_zs_zombie_demoknight" + "plugin" "npc_zs_cleaner" } } "38" { "cash" "4000" + "1.0" + { + "count" "0" + "plugin" "npc_wandering_spirit" + + } + "1.0" + { + "count" "2" + "health" "112500" + "is_boss" "1" + "plugin" "npc_random_zombie" + "cash" "0" + } + "1.0" + { + "count" "6" + "plugin" "npc_zs_manhattan_parrot" + } "5.0" { "count" "0" @@ -1670,7 +1697,7 @@ } "1.0" { - "count" "20" + "count" "10" "plugin" "npc_zs_sniper" } "0.0" @@ -1693,29 +1720,29 @@ } "1.0" { - "count" "5" + "count" "2" "health" "112500" "is_boss" "1" - "extra_damage" "3" "plugin" "npc_random_zombie" + "cash" "0" } - "5.0" //Overlord + "5.0" { - "count" "20" - "health" "25000" - "plugin" "npc_zmain_poisonzombie" + "count" "5" + "health" "100000" + "plugin" "npc_zs_zmain_poisonzombie" } - "5.0" //Overlord + "5.0" { - "count" "20" - "health" "25000" - "plugin" "npc_zmain_headcrabzombie" + "count" "5" + "health" "50000" + "plugin" "npc_zs_zmain_headcrabzombie" } - "0.0" //Overlord + "0.0" { - "count" "40" - "health" "25000" - "plugin" "npc_zmain_headcrab" + "count" "10" + "health" "10000" + "plugin" "npc_zs_zmain_headcrab" } } "40" @@ -1732,7 +1759,7 @@ "author" "Zombie Night Terror OST" } "setup" "60" - "1.0" + "5.0" { "count" "0" "health" "670000" @@ -1742,28 +1769,45 @@ "1.0" //inf untill death { "count" "2" - "health" "100000" + "health" "250000" "is_boss" "1" "plugin" "npc_zs_bonemesh" } "1.0" { - "count" "15" + "count" "5" "plugin" "npc_zs_medic_main" } "1.0" { - "count" "20" + "count" "2" + "health" "50000" + "plugin" "npc_zs_huntsman" + } + "1.0" + { + "count" "5" "plugin" "npc_zs_eradicator" } "1.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_zombie_breadmonster" } "1.0" { - "count" "10" + "count" "3" + "plugin" "npc_zs_zombie_soldier" + } + "1.0" + { + "count" "3" + "health" "50000" + "plugin" "npc_zs_zombie_scout" + } + "1.0" + { + "count" "5" "plugin" "npc_zs_mlsm" } "1.0" @@ -1773,7 +1817,7 @@ "is_boss" "1" "plugin" "npc_major_vulture" } - "1.0" + "10.0" { "count" "0" //he an expensive boi "health" "670000" @@ -1785,7 +1829,7 @@ "count" "2" "health" "250000" "is_boss" "1" - "plugin" "npc_combine_soldier_overlord" + "plugin" "npc_zombie_soldier_giant_grave" } "1.0" { @@ -1794,13 +1838,19 @@ } "1.0" { - "count" "10" + "count" "6" "health" "10000" "plugin" "npc_zs_kamikaze_demo" } "1.0" { - "count" "10" + "count" "2" + "health" "50000" + "plugin" "npc_infected_tomislav_main" + } + "1.0" + { + "count" "5" "plugin" "npc_zs_sam" } "1.0" @@ -1809,16 +1859,17 @@ "health" "35000" "plugin" "npc_zs_zombie_demoknight" } - "1.0" + "10.0" { "count" "1" "health" "250000" "is_boss" "1" "plugin" "npc_random_zombie" + "cash" "0" } - "5.0" + "1.0" { - "count" "10" + "count" "5" "plugin" "npc_zs_ihbc" } "1.0" @@ -1828,41 +1879,51 @@ } "1.0" { - "count" "15" + "count" "5" "health" "7500" "plugin" "npc_zs_zombie_spy" } "1.0" { - "count" "10" + "count" "5" "health" "25000" "plugin" "npc_zs_sniper" } "1.0" { - "count" "8" + "count" "5" "plugin" "npc_zs_firefighter" } "1.0" { - "count" "8" + "count" "5" "plugin" "npc_zs_zombie_fatspy" } "1.0" { - "count" "25" + "count" "2" + "plugin" "npc_zs_zombie_sniper_jarate" + } + "1.0" + { + "count" "5" "plugin" "npc_zs_medic_main" } "1.0" { - "count" "12" + "count" "5" "plugin" "npc_zs_vile_poisonheadcrab_zombie" } "1.0" { - "count" "20" + "count" "5" "plugin" "npc_zs_mlsm" } + "1.0" + { + "count" "6" + "plugin" "npc_zs_manhattan_parrot" + } "0.0" { "count" "0" @@ -1878,6 +1939,7 @@ "is_immune_to_nuke" "1" "is_health_scaling" "1" "data" "sc40;forth" + "is_outlined" "1" "plugin" "npc_doctor_unclean_one" } } diff --git a/addons/sourcemod/scripting/zombie_riot/elemental.sp b/addons/sourcemod/scripting/zombie_riot/elemental.sp index e29729bd0f..7af4bb6e16 100644 --- a/addons/sourcemod/scripting/zombie_riot/elemental.sp +++ b/addons/sourcemod/scripting/zombie_riot/elemental.sp @@ -1356,6 +1356,10 @@ static void Zombie_Spawning(int entity, int count) //it was the same bug alaxios had, in this case, it has to be reversed. health = RoundToNearest(float(health) / MultiGlobalHealth); } + if(health > 30000) + { + health = 30000; + } Enemy enemy; enemy.Index = NPC_GetByPlugin(name); diff --git a/addons/sourcemod/scripting/zombie_riot/npc.sp b/addons/sourcemod/scripting/zombie_riot/npc.sp index aed7a106e3..3031cd4258 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc.sp @@ -1238,6 +1238,7 @@ void NPC_ConfigSetup() Nest_OnMapStart_NPC(); ZSZmain_OnMapStart_NPC(); ZombieSummonRandom_OnMapStart_NPC(); + PoyoSummonRandom_OnMapStart_NPC(); Amplification_Precache(); Pregnant_Precache(); ZSHeadcrabZombie_OnMapStart_NPC(); @@ -1282,6 +1283,16 @@ void NPC_ConfigSetup() DasNaggenvatcher_OnMapStart(); StoneAgeMaker_OnMapStart_NPC(); MassShootingLover_OnMapStart_NPC(); + ZSZombine_OnMapStart_NPC(); + ZSMainHeadcrab_OnMapStart_NPC(); + ZSMainHeadcrabZombie_OnMapStart_NPC(); + ZSMainPoisonZombie_OnMapStart_NPC(); + ZSSoldierGiant_OnMapStart_NPC(); + ZSSoldierMinion_OnMapStart_NPC(); + Angryheadcrab_MapStart(); + Headcrabmilloperator_OnMapStart_NPC(); + ManhattanParrot_OnMapStart_NPC(); + InfectedTomislavMain_OnMapStart_NPC(); Allymedic_OnMapStart_NPC(); Allysoldier_OnMapStart_NPC(); Allyheavy_OnMapStart_NPC(); @@ -2738,6 +2749,9 @@ Action NpcSpecificOnTakeDamage(int victim, int &attacker, int &inflictor, float #include "npc/gmod_zs/45/npc_zs_zombie_engineer.sp" #include "npc/gmod_zs/45/npc_zs_medic_healer.sp" #include "npc/gmod_zs/45/npc_zs_huntsman.sp" +#include "npc/gmod_zs/45/npc_angryheadcrab.sp" +#include "npc/gmod_zs/45/npc_zs_hmo.sp" +#include "npc/gmod_zs/45/npc_infected_tomislav_main.sp" #include "npc/gmod_zs/60/npc_zs_eradicator.sp" #include "npc/gmod_zs/60/npc_zs_zombie_fatspy.sp" #include "npc/gmod_zs/60/npc_zs_medic_main.sp" @@ -2753,10 +2767,12 @@ Action NpcSpecificOnTakeDamage(int victim, int &attacker, int &inflictor, float #include "npc/gmod_zs/60/npc_zs_sniper.sp" #include "npc/gmod_zs/60/npc_zs_sam.sp" #include "npc/gmod_zs/60/npc_zs_mlsm.sp" +#include "npc/gmod_zs/60/npc_zs_manhattan_parrot.sp" #include "npc/gmod_zs/npc_zs_zmain.sp" #include "npc/gmod_zs/special/npc_zs_flesh_creeper.sp" #include "npc/gmod_zs/special/npc_zs_nest.sp" #include "npc/gmod_zs/special/npc_random_zombie.sp" +#include "npc/gmod_zs/special/npc_random_poyo.sp" #include "npc/gmod_zs/special/npc_zs_amplification.sp" #include "npc/gmod_zs/special/npc_zs_howler.sp" #include "npc/gmod_zs/special/npc_zs_poisonzombie_fortified_giant.sp" @@ -2766,6 +2782,12 @@ Action NpcSpecificOnTakeDamage(int victim, int &attacker, int &inflictor, float #include "npc/gmod_zs/special/npc_zs_malfunctioning_heavy.sp" #include "npc/gmod_zs/special/npc_zs_red_marrow.sp" #include "npc/gmod_zs/special/npc_zs_bonemesh.sp" +#include "npc/gmod_zs/special/npc_zs_zombine.sp" +#include "npc/gmod_zs/special/npc_zs_zmain_headcrab.sp" +#include "npc/gmod_zs/special/npc_zs_zmain_headcrabzombie.sp" +#include "npc/gmod_zs/special/npc_zs_zmain_poisonzombie.sp" +#include "npc/gmod_zs/special/npc_zs_soldier_giant_grave.sp" +#include "npc/gmod_zs/special/npc_zs_soldier_minion_grave.sp" #include "npc/gmod_zs/bosses/npc_zs_nightmare.sp" #include "npc/gmod_zs/bosses/npc_zs_sphynx.sp" #include "npc/gmod_zs/bosses/npc_zs_pregnant.sp" diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/15/npc_zs_headcrab.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/15/npc_zs_headcrab.sp index 7096d98f3b..07bad4ab80 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/15/npc_zs_headcrab.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/15/npc_zs_headcrab.sp @@ -43,7 +43,7 @@ void ZSHeadcrab_OnMapStart_NPC() strcopy(data.Icon, sizeof(data.Icon), "gmod_zs_headcrab"); data.IconCustom = true; data.Flags = 0; - data.Category = Type_Mutation; + data.Category = Type_GmodZS; data.Func = ClotSummon; NPC_Add(data); } diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/30/npc_zs_fast_headcrab.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/30/npc_zs_fast_headcrab.sp index d59e2b3ea3..c4c9f2d1b5 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/30/npc_zs_fast_headcrab.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/30/npc_zs_fast_headcrab.sp @@ -42,7 +42,7 @@ void FastHeadcrab_OnMapStart_NPC() strcopy(data.Icon, sizeof(data.Icon), "gmod_zs_fast_headcrab"); data.IconCustom = true; data.Flags = 0; - data.Category = Type_Mutation; + data.Category = Type_GmodZS; data.Func = ClotSummon; NPC_Add(data); } diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/30/npc_zs_spitter.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/30/npc_zs_spitter.sp index 7936bc07dc..4000cd7cd2 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/30/npc_zs_spitter.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/30/npc_zs_spitter.sp @@ -100,9 +100,9 @@ methodmap ZsSpitter < CSeaBody if(iActivity > 0) npc.StartActivity(iActivity); KillFeed_SetKillIcon(npc.index, "huntsman"); - npc.m_iBleedType = BLEEDTYPE_SEABORN; - npc.m_iStepNoiseType = STEPSOUND_NORMAL; - npc.m_iNpcStepVariation = STEPTYPE_SEABORN; + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; func_NPCDeath[npc.index] = ZsSpitter_NPCDeath; func_NPCOnTakeDamage[npc.index] = ZsSpitter_OnTakeDamage; @@ -170,7 +170,7 @@ public void ZsSpitter_ClotThink(int iNPC) npc.FaceTowards(vecTarget, 15000.0); npc.PlayRangedSound(); - int entity = npc.FireArrow(vecTarget, npc.m_bElite ? 40.0 : 40.0, 800.0, "models/weapons/w_bugbait.mdl"); + int entity = npc.FireArrow(vecTarget, 40.0, 800.0, "models/weapons/w_bugbait.mdl"); // 280 * 0.15 // 320 * 0.15 @@ -250,10 +250,9 @@ static Action zs_spitter_StartTouch(int entity, int target) if(inflictor == -1) inflictor = owner; - float DamageDeal = fl_rocket_particle_dmg[entity]; + float DamageDeal = 40.0; if(ShouldNpcDealBonusDamage(target)) - DamageDeal *= h_BonusDmgToSpecialArrow[entity]; - KillFeed_SetKillIcon(owner, "ball"); + DamageDeal *= 0.5; SDKHooks_TakeDamage(target, owner, inflictor, DamageDeal, DMG_BULLET|DMG_PREVENT_PHYSICS_FORCE, -1); //acts like a kinetic rocket if(target <= MaxClients && !IsInvuln(target)) if(!HasSpecificBuff(target, "Fluid Movement")) diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_angryheadcrab.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_angryheadcrab.sp new file mode 100644 index 0000000000..72fe00d1da --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_angryheadcrab.sp @@ -0,0 +1,245 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + "npc/headcrab/die1.wav", + "npc/headcrab/die2.wav" +}; + +static const char g_HurtSound[][] = { + "npc/headcrab/pain1.wav", + "npc/headcrab/pain2.wav", + "npc/headcrab/pain3.wav" +}; + +static const char g_IdleSound[][] = { + "npc/headcrab/alert1.wav", + "npc/headcrab/idle3.wav" +}; + +static const char g_MeleeHitSounds[][] = { + "npc/headcrab/headbite.wav" +}; + +static const char g_MeleeAttackSounds[][] = { + "npc/headcrab/attack1.wav", + "npc/headcrab/attack2.wav", + "npc/headcrab/attack3.wav" +}; + +void Angryheadcrab_MapStart() +{ + PrecacheSoundArray(g_DeathSounds); + PrecacheSoundArray(g_MeleeAttackSounds); + PrecacheSoundArray(g_MeleeHitSounds); + PrecacheSoundArray(g_IdleSound); + PrecacheSoundArray(g_HurtSound); + + PrecacheModel("models/headcrabclassic.mdl"); + + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Angry Headcrab"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_angryheadcrab"); + strcopy(data.Icon, sizeof(data.Icon), "ds_runner"); + data.IconCustom = true; + data.Flags = 0; + data.Category = Type_GmodZS; + data.Func = ClotSummon; + NPC_Add(data); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team, const char[] data) +{ + return Angryheadcrab(vecPos, vecAng, team, data); +} + +methodmap Angryheadcrab < CSeaBody +{ + public void PlayIdleSound() + { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleSound[GetRandomInt(0, sizeof(g_IdleSound) - 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() + { + EmitSoundToAll(g_HurtSound[GetRandomInt(0, sizeof(g_HurtSound) - 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_AUTO, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME,_); + } + + public Angryheadcrab(float vecPos[3], float vecAng[3], int ally, const char[] data) + { + Angryheadcrab npc = view_as(CClotBody(vecPos, vecAng, "models/headcrabclassic.mdl", "1.35", data[0] ? "600" : "400", ally, false)); + // 3000 x 0.15 + // 4000 x 0.15 + + npc.SetElite(view_as(data[0])); + i_NpcWeight[npc.index] = 0; + npc.SetActivity("ACT_RUN"); + KillFeed_SetKillIcon(npc.index, "bread_bite"); + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + func_NPCDeath[npc.index] = Angryheadcrab_NPCDeath; + func_NPCOnTakeDamage[npc.index] = Angryheadcrab_OnTakeDamage; + func_NPCThink[npc.index] = Angryheadcrab_ClotThink; + + npc.m_flSpeed = data[0] ? 475.0 : 330.0; // 1.9 x 250 + npc.m_flGetClosestTargetTime = 0.0; + npc.m_flNextMeleeAttack = 0.0; + npc.m_flAttackHappens = 0.0; + f_ExtraOffsetNpcHudAbove[npc.index] = -65.0; + + SetEntityRenderColor(npc.index, 255, 0, 0, 255); + return npc; + } +} + +public void Angryheadcrab_ClotThink(int iNPC) +{ + Angryheadcrab npc = view_as(iNPC); + + float gameTime = GetGameTime(npc.index); + if(npc.m_flNextDelayTime > gameTime) + return; + + npc.m_flNextDelayTime = gameTime + DEFAULT_UPDATE_DELAY_FLOAT; + npc.Update(); + + if(npc.m_blPlayHurtAnimation) + { + //npc.AddGesture("ACT_GESTURE_FLINCH_HEAD", false); + npc.PlayHurtSound(); + npc.m_blPlayHurtAnimation = false; + } + + if(npc.m_flNextThinkTime > gameTime) + return; + + npc.m_flNextThinkTime = gameTime + 0.1; + + if(npc.m_iTarget && !IsValidEnemy(npc.index, npc.m_iTarget)) + npc.m_iTarget = 0; + + if(!npc.m_iTarget || npc.m_flGetClosestTargetTime < gameTime) + { + npc.m_iTarget = GetClosestTarget(npc.index); + npc.m_flGetClosestTargetTime = gameTime + 1.0; + } + + if(npc.m_iTarget > 0) + { + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float distance = GetVectorDistance(vecTarget, VecSelfNpc, true); + + if(distance < npc.GetLeadRadius()) + { + float vPredictedPos[3]; PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + } + + npc.StartPathing(); + + if(npc.m_flAttackHappens) + { + if(npc.m_flAttackHappens < gameTime) + { + npc.m_flAttackHappens = 0.0; + + Handle swingTrace; + npc.FaceTowards(vecTarget, 15000.0); + if(npc.DoSwingTrace(swingTrace, npc.m_iTarget, _, _, _, _)) + { + int target = TR_GetEntityIndex(swingTrace); + + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + + if(target > 0) + { + npc.PlayMeleeHitSound(); + SDKHooks_TakeDamage(target, npc.index, npc.index, npc.m_bElite ? 150.0 : 100.0, DMG_CLUB); + StartBleedingTimer(target, npc.index, 5.0, 2, -1, DMG_TRUEDAMAGE, 0); + // 280 x 0.15 + // 340 x 0.15 + } + } + + delete swingTrace; + } + } + + if(distance < 10000.0 && npc.m_flNextMeleeAttack < gameTime) + { + int target = Can_I_See_Enemy(npc.index, npc.m_iTarget); + if(IsValidEnemy(npc.index, target)) + { + npc.m_iTarget = target; + + npc.AddGesture("ACT_RANGE_ATTACK1"); + + npc.PlayMeleeSound(); + + npc.m_flAttackHappens = gameTime + 0.45; + + //npc.m_flDoingAnimation = gameTime + 1.2; + npc.m_flNextMeleeAttack = gameTime + 1.25; + npc.m_flHeadshotCooldown = gameTime + 1.25; + } + } + } + else + { + npc.StopPathing(); + } + + npc.PlayIdleSound(); +} + +public Action Angryheadcrab_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + if(attacker < 1) + return Plugin_Continue; + + Angryheadcrab npc = view_as(victim); + if(npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + return Plugin_Changed; +} + +void Angryheadcrab_NPCDeath(int entity) +{ + Angryheadcrab npc = view_as(entity); + if(!npc.m_bGib) + npc.PlayDeathSound(); + + float vecMe[3]; WorldSpaceCenter(npc.index, vecMe); + Explode_Logic_Custom(40.0, npc.index, npc.index, -1, vecMe, 200.0, 1.0, _, true, 15, _, _, Angryheadcrab_ExplodePost); +} +static void Angryheadcrab_ExplodePost(int attacker, int victim, float damage, int weapon) +{ + StartBleedingTimer(victim, attacker, 5.0, 2, -1, DMG_TRUEDAMAGE, 0); +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_infected_tomislav_main.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_infected_tomislav_main.sp new file mode 100644 index 0000000000..30157ef48f --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_infected_tomislav_main.sp @@ -0,0 +1,284 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + "vo/heavy_paincrticialdeath01.mp3", + "vo/heavy_paincrticialdeath02.mp3", + "vo/heavy_paincrticialdeath03.mp3", +}; + +static const char g_HurtSounds[][] = { + "vo/heavy_painsharp01.mp3", + "vo/heavy_painsharp02.mp3", + "vo/heavy_painsharp03.mp3", + "vo/heavy_painsharp04.mp3", + "vo/heavy_painsharp05.mp3", +}; + + +static const char g_IdleAlertedSounds[][] = { + "vo/taunts/heavy_taunts16.mp3", + "vo/taunts/heavy_taunts18.mp3", + "vo/taunts/heavy_taunts19.mp3", +}; + + +void InfectedTomislavMain_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("models/player/heavy.mdl"); + PrecacheSound("weapons/tomislav_shoot.wav"); + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Infected Tomislav Main"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_infected_tomislav_main"); + strcopy(data.Icon, sizeof(data.Icon), "heavy"); + data.IconCustom = false; + data.Flags = 0; + data.Category = Type_GmodZS; + data.Func = ClotSummon; + NPC_Add(data); + +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return InfectedTomislavMain(vecPos, vecAng, team); +} + +methodmap InfectedTomislavMain < 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); + + } + + 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, "common/null.wav"); + EmitSoundToAll("weapons/tomislav_shoot.wav", this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, 0.70); + } + this.i_GunMode = 0; + } + else + { + if(this.i_GunMode != 1) + { + StopSound(this.index, SNDCHAN_STATIC, "weapons/tomislav_shoot.wav"); + EmitSoundToAll("common/null.wav", this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, 0.70); + } + this.i_GunMode = 1; + } + } + + public InfectedTomislavMain(float vecPos[3], float vecAng[3], int ally) + { + InfectedTomislavMain npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "30000", ally)); + + i_NpcWeight[npc.index] = 1; + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_MP_DEPLOYED_PRIMARY"); + if(iActivity > 0) npc.StartActivity(iActivity); + + func_NPCDeath[npc.index] = InfectedTomislavMain_NPCDeath; + func_NPCOnTakeDamage[npc.index] = InfectedTomislavMain_OnTakeDamage; + func_NPCThink[npc.index] = InfectedTomislavMain_ClotThink; + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + npc.StartPathing(); + npc.m_flSpeed = 231.0; + + int skin = 5; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable1 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_tomislav/c_tomislav.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + + npc.m_iWearable2 = npc.EquipItem("head", "models/player/items/all_class/all_domination_2009_heavy.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable2, "SetModelScale"); + + npc.m_iWearable3 = npc.EquipItem("head", "models/player/items/heavy/heavy_zombie.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable3, "SetModelScale"); + + SetEntProp(npc.m_iWearable1, Prop_Send, "m_nSkin", 1); + SetEntProp(npc.m_iWearable2, Prop_Send, "m_nSkin", 1); + SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", 1); + return npc; + } +} + +public void InfectedTomislavMain_ClotThink(int iNPC) +{ + InfectedTomislavMain 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); + } + InfectedTomislavMainSelfDefense(npc); + } + else + { + npc.PlayMinigunSound(false); + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleAlertSound(); +} + +public Action InfectedTomislavMain_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + InfectedTomislavMain 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 InfectedTomislavMain_NPCDeath(int entity) +{ + InfectedTomislavMain npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + StopSound(npc.index, SNDCHAN_STATIC, "common/null.wav"); + StopSound(npc.index, SNDCHAN_STATIC, "weapons/tomislav_shoot.wav"); + StopSound(npc.index, SNDCHAN_STATIC, "common/null.wav"); + StopSound(npc.index, SNDCHAN_STATIC, "weapons/tomislav_shoot.wav"); + + 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 InfectedTomislavMainSelfDefense(InfectedTomislavMain npc) +{ + 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.AddGesture("ACT_MP_ATTACK_STAND_PRIMARY", false); + 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 ); + if(IsValidEnemy(npc.index, target)) + { + float damageDealt = 16.0; + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 4.0; + + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_BULLET, -1, _, vecHit); + } + } + delete swingTrace; + } + if(SpinSound) + npc.PlayMinigunSound(false); +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_hmo.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_hmo.sp new file mode 100644 index 0000000000..252bf461b0 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_hmo.sp @@ -0,0 +1,482 @@ +#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_IdleSounds[][] = { + "vo/pyro_jeers01.mp3", + "vo/pyro_jeers02.mp3", +}; + +static const char g_IdleAlertedSounds[][] = { + "vo/taunts/pyro_taunts01.mp3", + "vo/taunts/pyro_taunts02.mp3", + "vo/taunts/pyro_taunts03.mp3", +}; +static const char g_RangedAttackSounds[][] = { + "weapons/dragons_fury_shoot.wav", +}; + +static const char g_RangedReloadSound[][] = { + "weapons/dragons_fury_pressure_build.wav", +}; + +void Headcrabmilloperator_OnMapStart_NPC() +{ + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Headcrab Mill Operator"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_zs_hmo"); + data.Category = Type_GmodZS; + data.Func = ClotSummon; + data.Precache = ClotPrecache; + strcopy(data.Icon, sizeof(data.Icon), "scout_stun"); //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. + NPC_Add(data); +} +static float fl_npc_basespeed; +static void ClotPrecache() +{ + PrecacheSoundArray(g_DeathSounds); + PrecacheSoundArray(g_HurtSounds); + PrecacheSoundArray(g_IdleSounds); + PrecacheSoundArray(g_IdleAlertedSounds); + PrecacheSoundArray(g_RangedAttackSounds); + PrecacheSoundArray(g_RangedReloadSound); + PrecacheModel("models/player/pyro.mdl"); +} +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return Headcrabmilloperator(vecPos, vecAng, team); +} + +methodmap Headcrabmilloperator < CClotBody +{ + + public void PlayIdleSound() { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + EmitSoundToAll(g_IdleSounds[GetRandomInt(0, sizeof(g_IdleSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, RUINA_NPC_PITCH); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(24.0, 48.0); + + + } + + 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, RUINA_NPC_PITCH); + 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, RUINA_NPC_PITCH); + + + + } + + public void PlayDeathSound() { + + EmitSoundToAll(g_DeathSounds[GetRandomInt(0, sizeof(g_DeathSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, RUINA_NPC_PITCH); + + + } + public void PlayRangedSound() { + EmitSoundToAll(g_RangedAttackSounds[GetRandomInt(0, sizeof(g_RangedAttackSounds) - 1)], this.index, _, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, RUINA_NPC_PITCH); + + + } + public void PlayRangedReloadSound() { + EmitSoundToAll(g_RangedReloadSound[GetRandomInt(0, sizeof(g_RangedReloadSound) - 1)], this.index, _, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, RUINA_NPC_PITCH); + + + } + + + public Headcrabmilloperator(float vecPos[3], float vecAng[3], int ally) + { + Headcrabmilloperator npc = view_as(CClotBody(vecPos, vecAng, "models/player/pyro.mdl", "1.0", "17500", 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(5); + 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(NPC_Death); + func_NPCOnTakeDamage[npc.index] = view_as(OnTakeDamage); + func_NPCThink[npc.index] = view_as(ClotThink); + + fl_npc_basespeed = 200.0; + npc.m_flSpeed = 200.0; + npc.m_flGetClosestTargetTime = 0.0; + npc.StartPathing(); + + npc.m_iWearable1 = npc.EquipItem("head", WEAPON_CUSTOM_WEAPONRY_1); + SetVariantString("1.0"); + SetVariantInt(32768); + AcceptEntityInput(npc.m_iWearable1, "SetBodyGroup"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + + npc.m_iWearable2 = npc.EquipItem("head", "models/workshop/player/items/all_class/witchhat/witchhat_pyro.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable2, "SetModelScale"); + + npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/player/items/pyro/hw2013_hardheaded_hardware/hw2013_hardheaded_hardware.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable3, "SetModelScale"); + + npc.m_iWearable4 = npc.EquipItem("head", "models/workshop/player/items/pyro/hw2013_gristly_gumbo_pot/hw2013_gristly_gumbo_pot.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable4, "SetModelScale"); + + npc.m_iWearable5 = npc.EquipItem("head", "models/workshop/player/items/pyro/hwn2025_industrial/hwn2025_industrial.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable5, "SetModelScale"); + + + int skin = 1; //1=blue, 0=red + SetVariantInt(1); + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + 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); + + fl_ruina_battery_max[npc.index] = 6000.0; + fl_ruina_battery[npc.index] = 0.0; + b_ruina_battery_ability_active[npc.index] = false; + fl_ruina_battery_timer[npc.index] = 0.0; + + Ruina_Set_Heirarchy(npc.index, RUINA_RANGED_NPC); //is a ranged npc + + return npc; + } + + +} + + +static void ClotThink(int iNPC) +{ + Headcrabmilloperator npc = view_as(iNPC); + + float GameTime = GetGameTime(npc.index); + if(npc.m_flNextDelayTime > GameTime) + { + return; + } + + + + npc.m_flNextDelayTime = GameTime + 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 > GameTime) + { + return; + } + + npc.m_flNextThinkTime = GameTime + 0.1; + + Ruina_Add_Battery(npc.index, 1.5); + + + if(npc.m_flGetClosestTargetTime < GameTime) + { + npc.m_iTarget = GetClosestTarget(npc.index); + npc.m_flGetClosestTargetTime = GameTime + GetRandomRetargetTime(); + } + + int PrimaryThreatIndex = npc.m_iTarget; + + if(fl_ruina_battery[npc.index]>fl_ruina_battery_max[npc.index]) + { + if(Zombies_Currently_Still_Ongoing < NPC_HARD_LIMIT) + { + fl_ruina_battery[npc.index] = 0.0; + Headcrabmilloperator_Spawn_Self(npc); + } + + } + + if(fl_ruina_battery_timer[npc.index](victim); + + if(attacker <= 0) + return Plugin_Continue; + + Ruina_NPC_OnTakeDamage_Override(npc.index, attacker, inflictor, damage, damagetype, weapon, damageForce, damagePosition, damagecustom); + + //Ruina_Add_Battery(npc.index, damage); //turn damage taken into energy + + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + + return Plugin_Changed; +} + +static void NPC_Death(int entity) +{ + Headcrabmilloperator npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + Ruina_NPCDeath_Override(entity); + + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + if(IsValidEntity(npc.m_iWearable5)) + RemoveEntity(npc.m_iWearable5); +} +static void Headcrabmilloperator_Spawn_Minnions(Headcrabmilloperator npc) +{ + int maxhealth = ReturnEntityMaxHealth(npc.index); + + float pos[3]; GetEntPropVector(npc.index, Prop_Data, "m_vecAbsOrigin", pos); + float ang[3]; GetEntPropVector(npc.index, Prop_Data, "m_angRotation", ang); + + int spawn_index; + + spawn_index = NPC_CreateByName("npc_angryheadcrab", npc.index, pos, ang, GetTeam(npc.index)); + maxhealth = RoundToNearest(maxhealth * 0.25); + + if(spawn_index > MaxClients) + { + NpcAddedToZombiesLeftCurrently(spawn_index, true); + SetEntProp(spawn_index, Prop_Data, "m_iHealth", maxhealth); + SetEntProp(spawn_index, Prop_Data, "m_iMaxHealth", maxhealth); + + float WorldSpaceVec[3]; WorldSpaceCenter(spawn_index, WorldSpaceVec); + ParticleEffectAt(WorldSpaceVec, "teleported_blue", 0.5); + } + +} +static void Headcrabmilloperator_Spawn_Self(Headcrabmilloperator npc) +{ + int maxhealth = ReturnEntityMaxHealth(npc.index); + + if(maxhealth<100) + return; + + float pos[3]; GetEntPropVector(npc.index, Prop_Data, "m_vecAbsOrigin", pos); + float ang[3]; GetEntPropVector(npc.index, Prop_Data, "m_angRotation", ang); + + int spawn_index; + + spawn_index = NPC_CreateByName("npc_ruina_hmo", npc.index, pos, ang, GetTeam(npc.index)); + maxhealth = RoundToNearest(maxhealth * 0.5); + + if(spawn_index > MaxClients) + { + NpcAddedToZombiesLeftCurrently(spawn_index, true); + SetEntProp(spawn_index, Prop_Data, "m_iHealth", maxhealth); + SetEntProp(spawn_index, Prop_Data, "m_iMaxHealth", maxhealth); + float WorldSpaceVec[3]; WorldSpaceCenter(spawn_index, WorldSpaceVec); + ParticleEffectAt(WorldSpaceVec, "teleported_red", 0.5); + } +} +static void Headcrabmilloperator_SelfDefense(Headcrabmilloperator npc, float gameTime, int Anchor_Id) //ty artvin +{ + int GetClosestEnemyToAttack; + //Ranged units will behave differently. + //Get the closest visible target via distance checks, not via pathing check. + GetClosestEnemyToAttack = GetClosestTarget(npc.index,_,_,_,_,_,_,true,_,_,true); //works with masters, slaves not so much. seems to work with independant npc's too + if(!IsValidEnemy(npc.index,GetClosestEnemyToAttack)) //no target, what to do while idle + { + return; + } + float vecTarget[3]; WorldSpaceCenter(GetClosestEnemyToAttack, vecTarget); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + if(flDistanceToTarget < (1000.0*1000.0)) + { + if(gameTime > npc.m_flNextRangedAttack) + { + fl_ruina_in_combat_timer[npc.index]=gameTime+5.0; + npc.AddGesture("ACT_MP_ATTACK_STAND_MELEE_ALLCLASS", true); + npc.PlayRangedSound(); + //after we fire, we will have a short delay beteween the actual laser, and when it happens + //This will predict as its relatively easy to dodge + float projectile_speed = 500.0; + //lets pretend we have a projectile. + WorldSpaceCenter(GetClosestEnemyToAttack, vecTarget); + float DamageDone = 100.0; + npc.FireParticleRocket(vecTarget, DamageDone, projectile_speed, 0.0, "spell_fireball_small_blue", false, true, false,_,_,_,10.0); + npc.FaceTowards(vecTarget, 20000.0); + npc.m_flNextRangedAttack = GetGameTime(npc.index) + 5.0; + npc.PlayRangedReloadSound(); + } + } + else + { + if(IsValidEntity(Anchor_Id)) + { + + CClotBody npc2 = view_as(Anchor_Id); + int target = npc2.m_iTarget; + + if(IsValidEnemy(npc.index,target)) + { + GetClosestEnemyToAttack = target; + WorldSpaceCenter(GetClosestEnemyToAttack, vecTarget ); + + fl_ruina_in_combat_timer[npc.index]=gameTime+5.0; + + flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + if(gameTime > npc.m_flNextRangedAttack) + { + npc.AddGesture("ACT_MP_ATTACK_STAND_MELEE_ALLCLASS", true); + npc.PlayRangedSound(); + //after we fire, we will have a short delay beteween the actual laser, and when it happens + //This will predict as its relatively easy to dodge + float projectile_speed = 500.0; + //lets pretend we have a projectile. + WorldSpaceCenter(GetClosestEnemyToAttack, vecTarget); + float DamageDone = 100.0; + npc.FireParticleRocket(vecTarget, DamageDone, projectile_speed, 0.0, "spell_fireball_small_blue", false, true, false,_,_,_,10.0); + npc.FaceTowards(vecTarget, 20000.0); + npc.m_flNextRangedAttack = GetGameTime(npc.index) + 5.0; + npc.PlayRangedReloadSound(); + } + } + } + } + if(npc.m_bAllowBackWalking) + { + npc.FaceTowards(vecTarget, 350.0); + } + npc.m_iTarget = GetClosestEnemyToAttack; +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_huntsman.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_huntsman.sp index 500d03b441..7a376771b0 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_huntsman.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_huntsman.sp @@ -44,7 +44,7 @@ void ZSHuntsman_OnMapStart_NPC() strcopy(data.Icon, sizeof(data.Icon), "sniper_bow"); data.IconCustom = false; data.Flags = 0; - data.Category = Type_Aperture; + data.Category = Type_GmodZS; data.Func = ClotSummon; NPC_Add(data); } @@ -153,8 +153,6 @@ methodmap ZSHuntsman < CClotBody return npc; } - - } @@ -214,7 +212,7 @@ public void ZSHuntsman_ClotThink(int iNPC) npc.SetGoalEntity(PrimaryThreatIndex); } - if(flDistanceToTarget < 160000) + if(flDistanceToTarget < 1440000) { int Enemy_I_See; diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_kamikaze_demo.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_kamikaze_demo.sp index ace77cde01..2a3c0dd353 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_kamikaze_demo.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_kamikaze_demo.sp @@ -37,7 +37,7 @@ void InfectedKamikaze_OnMapStart_NPC() strcopy(data.Icon, sizeof(data.Icon), "demo"); data.IconCustom = false; data.Flags = 0; - data.Category = Type_Common; + data.Category = Type_GmodZS; data.Func = ClotSummon; NPC_Add(data); } @@ -313,7 +313,7 @@ public void InfectedKamikaze_NPCDeath(int entity) pack.WriteCell(100); RequestFrame(DelayExplosiveMakeExplosion, pack); */ - makeexplosion(entity, startPosition, 65, 125, _, true); + makeexplosion(entity, startPosition, 65, 200, _, true); } else { diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_medic_healer.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_medic_healer.sp index 1e63370f6b..9707a1c34f 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_medic_healer.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_medic_healer.sp @@ -29,7 +29,7 @@ void ZSMedicHealer_OnMapStart_NPC() strcopy(data.Icon, sizeof(data.Icon), "medic"); data.IconCustom = false; data.Flags = 0; - data.Category = Type_Common; + data.Category = Type_GmodZS; data.Func = ClotSummon; NPC_Add(data); } @@ -88,7 +88,7 @@ methodmap ZSMedicHealer < CClotBody } public ZSMedicHealer(float vecPos[3], float vecAng[3], int ally) { - ZSMedicHealer npc = view_as(CClotBody(vecPos, vecAng, "models/player/medic.mdl", "1.0", "10000", ally)); + ZSMedicHealer npc = view_as(CClotBody(vecPos, vecAng, "models/player/medic.mdl", "1.0", "15000", ally)); i_NpcWeight[npc.index] = 1; diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_ninja_zombie_spy.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_ninja_zombie_spy.sp index d0f0015934..d563f62fe6 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_ninja_zombie_spy.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_ninja_zombie_spy.sp @@ -167,6 +167,9 @@ methodmap NinjaSpy < CClotBody SetEntPropFloat(npc.m_iWearable2, Prop_Send, "m_fadeMinDist", 500.0); SetEntPropFloat(npc.m_iWearable2, Prop_Send, "m_fadeMaxDist", 750.0); + + SetEntPropFloat(npc.m_iWearable3, Prop_Send, "m_fadeMinDist", 500.0); + SetEntPropFloat(npc.m_iWearable3, Prop_Send, "m_fadeMaxDist", 750.0); SetEntProp(npc.m_iWearable2, Prop_Send, "m_nSkin", 1); SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", 1); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_demoknight.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_demoknight.sp index 1267dabe67..0e13ab92cd 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_demoknight.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_demoknight.sp @@ -77,7 +77,7 @@ methodmap InfectedDemoMain < CClotBody } public InfectedDemoMain(float vecPos[3], float vecAng[3], int ally) { - InfectedDemoMain npc = view_as(CClotBody(vecPos, vecAng, "models/player/demo.mdl", "1.0", "17500", ally)); + InfectedDemoMain npc = view_as(CClotBody(vecPos, vecAng, "models/player/demo.mdl", "1.0", "25000", ally)); i_NpcWeight[npc.index] = 1; @@ -300,6 +300,4 @@ public void InfectedDemoMain_NPCDeath(int entity) RemoveEntity(npc.m_iWearable2); if(IsValidEntity(npc.m_iWearable3)) RemoveEntity(npc.m_iWearable3); -} - - +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_engineer.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_engineer.sp index 2a27961729..5d1e0a9adc 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_engineer.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_engineer.sp @@ -63,7 +63,7 @@ void InfectedEngineer_OnMapStart_NPC() strcopy(data.Icon, sizeof(data.Icon), "Engineer"); data.IconCustom = false; data.Flags = 0; - data.Category = Type_Common; + data.Category = Type_GmodZS; data.Func = ClotSummon; NPC_Add(data); @@ -132,7 +132,7 @@ methodmap InfectedEngineer < CClotBody public InfectedEngineer(float vecPos[3], float vecAng[3], int ally) { - InfectedEngineer npc = view_as(CClotBody(vecPos, vecAng, "models/player/engineer.mdl", "1.00", "12500", ally)); + InfectedEngineer npc = view_as(CClotBody(vecPos, vecAng, "models/player/engineer.mdl", "1.00", "20000", ally)); i_NpcWeight[npc.index] = 1; diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_heavy.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_heavy.sp index 16c89ee1e8..e862923b61 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_heavy.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_heavy.sp @@ -86,7 +86,7 @@ methodmap InfectedHeavy < CClotBody public InfectedHeavy(float vecPos[3], float vecAng[3], int ally) { - InfectedHeavy npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "15000", ally)); + InfectedHeavy npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "30000", ally)); i_NpcWeight[npc.index] = 2; npc.SetActivity("ACT_MP_RUN_MELEE"); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_scout.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_scout.sp index f6a6a241a4..69376e13ba 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_scout.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_scout.sp @@ -132,7 +132,7 @@ methodmap ZSscout < CClotBody public ZSscout(float vecPos[3], float vecAng[3], int ally) { - ZSscout npc = view_as(CClotBody(vecPos, vecAng, "models/player/scout.mdl", "1.0", "12500", ally)); + ZSscout npc = view_as(CClotBody(vecPos, vecAng, "models/player/scout.mdl", "1.0", "15000", ally)); i_NpcWeight[npc.index] = 1; diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_sniper_jarate.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_sniper_jarate.sp index db72807656..23293c696f 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_sniper_jarate.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_sniper_jarate.sp @@ -83,7 +83,7 @@ methodmap InfectedSniperjarate < CClotBody public InfectedSniperjarate(float vecPos[3], float vecAng[3], int ally) { - InfectedSniperjarate npc = view_as(CClotBody(vecPos, vecAng, "models/player/sniper.mdl", "1.0", "12500", ally)); + InfectedSniperjarate npc = view_as(CClotBody(vecPos, vecAng, "models/player/sniper.mdl", "1.0", "22500", ally)); i_NpcWeight[npc.index] = 1; npc.SetActivity("ACT_MP_RUN_MELEE"); @@ -183,7 +183,8 @@ public void InfectedSniperjarate_ClotThink(int iNPC) if(target > 0) { npc.PlayMeleeHitSound(); - SDKHooks_TakeDamage(target, npc.index, npc.index, 160.0, DMG_CLUB); + SDKHooks_TakeDamage(target, npc.index, npc.index, 200.0, DMG_CLUB); + Elemental_AddPheromoneDamage(target, npc.index, npc.index ? 100 : 50); if(!NpcStats_IsEnemySilenced(npc.index)) { diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_soldier.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_soldier.sp index 3b702d6a03..1266c014fa 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_soldier.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_soldier.sp @@ -42,7 +42,7 @@ void ZSoldierGrave_OnMapStart_NPC() strcopy(data.Icon, sizeof(data.Icon), "soldier"); data.IconCustom = false; data.Flags = 0; - data.Category = Type_Common; + data.Category = Type_GmodZS; data.Func = ClotSummon; data.Precache = ClotPrecache; NPC_Add(data); @@ -96,7 +96,7 @@ methodmap ZSoldierGrave < CClotBody public ZSoldierGrave(float vecPos[3], float vecAng[3], int ally) { - ZSoldierGrave npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "20000", ally)); + ZSoldierGrave npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "30000", ally)); i_NpcWeight[npc.index] = 1; @@ -235,51 +235,58 @@ static void ZSoldierGrave_ClotThink(int iNPC) static int ZSoldierGrave_Work(ZSoldierGrave npc, float gameTime, int target, float distance, float vecTarget[3]) { - if(npc.m_flAttackHappens || !npc.m_iAmmo) - { - if(!npc.m_flAttackHappens) - { - npc.m_flAttackHappens=gameTime+1.0; - npc.AddGesture("ACT_MP_RELOAD_STAND_PRIMARY", true,_,_,1.1); - npc.m_flAttackHappenswillhappen=false; - //npc.PlayReloadSound(); - } - if(gameTime > npc.m_flAttackHappens) - { - npc.m_iAmmo = npc.m_iMaxAmmo; - npc.m_flAttackHappens=0.0; - } - } - if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 25.0) || npc.m_flAttackHappenswillhappen) - { - int Enemy_I_See = Can_I_See_Enemy(npc.index, target); - if((gameTime > npc.m_flNextRangedAttack && IsValidEnemy(npc.index, Enemy_I_See)) || npc.m_flAttackHappenswillhappen) - { - npc.AddGesture("ACT_MP_ATTACK_STAND_PRIMARY", true); - float ProjectileSpeed = 700.0; - WorldSpaceCenter(Enemy_I_See, vecTarget); - PredictSubjectPositionForProjectiles(npc, target, ProjectileSpeed, _,vecTarget); - npc.FaceTowards(vecTarget, 20000.0); - npc.FireRocket(vecTarget, 135.0, ProjectileSpeed); - npc.PlayRangeSound(); + if(npc.m_flAttackHappens || !npc.m_iAmmo) + { + if(!npc.m_flAttackHappens) + { + npc.m_flAttackHappens = gameTime + 1.1; + npc.AddGesture("ACT_MP_RELOAD_STAND_PRIMARY", true, _, _, 1.1); + npc.m_flAttackHappenswillhappen = false; + } - npc.m_flNextRangedAttack=gameTime+2.0; - npc.m_flAttackHappenswillhappen = true; - npc.m_iAmmo--; - } - } - if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 9.0)||ShouldNpcDealBonusDamage(target)) - { - return 0; - } - else if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 8.0)) - { - if(Can_I_See_Enemy_Only(npc.index, target)) - { - return 2; - } - } - return 1; + if(gameTime > npc.m_flAttackHappens) + { + npc.m_iAmmo = npc.m_iMaxAmmo; + npc.m_flAttackHappens = 0.0; + } + } + + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 25.0) || npc.m_flAttackHappenswillhappen) + { + int Enemy_I_See = Can_I_See_Enemy(npc.index, target); + + if(!npc.m_flAttackHappens && ((gameTime > npc.m_flNextRangedAttack && IsValidEnemy(npc.index, Enemy_I_See)) || npc.m_flAttackHappenswillhappen)) + { + npc.AddGesture("ACT_MP_ATTACK_STAND_PRIMARY", true); + float ProjectileSpeed = 700.0; + + WorldSpaceCenter(target, vecTarget); + PredictSubjectPositionForProjectiles(npc, target, ProjectileSpeed, _, vecTarget); + + npc.FaceTowards(vecTarget, 20000.0); + npc.FireRocket(vecTarget, 135.0, ProjectileSpeed); + npc.PlayRangeSound(); + + npc.m_flNextRangedAttack = gameTime + 2.0; + npc.m_flAttackHappenswillhappen = true; + npc.m_iAmmo--; + } + } + + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 9.0) || ShouldNpcDealBonusDamage(target)) + { + return 0; // Chase + } + else if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 8.0)) + { + if(Can_I_See_Enemy_Only(npc.index, target)) + { + return 2; // Backoff + } + } + + // 위 조건들에 해당하지 않는 "애매한 거리"이거나 재장전 중일 때의 기본 행동 + return 1; // Stand / Attack Position } static Action ZSoldierGrave_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_soldier_pickaxe.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_soldier_pickaxe.sp index 2b41f35f5f..971a5ffafb 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_soldier_pickaxe.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_zombie_soldier_pickaxe.sp @@ -88,7 +88,7 @@ methodmap ZSsoldier < CClotBody public ZSsoldier(float vecPos[3], float vecAng[3], int ally) { - ZSsoldier npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "22000", ally)); + ZSsoldier npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "40000", ally)); i_NpcWeight[npc.index] = 3; npc.SetActivity("ACT_MP_RUN_MELEE"); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_cleaner.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_cleaner.sp index 11d117d635..59042a1df2 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_cleaner.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_cleaner.sp @@ -101,7 +101,7 @@ methodmap InfectedCleaner < CClotBody public InfectedCleaner(float vecPos[3], float vecAng[3], int ally) { - InfectedCleaner npc = view_as(CClotBody(vecPos, vecAng, "models/player/pyro.mdl", "1.0", "40000", ally)); + InfectedCleaner npc = view_as(CClotBody(vecPos, vecAng, "models/player/pyro.mdl", "1.0", "50000", ally)); i_NpcWeight[npc.index] = 1; FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_combine_soldier_elite.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_combine_soldier_elite.sp index f45623f820..95a96e347d 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_combine_soldier_elite.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_combine_soldier_elite.sp @@ -68,12 +68,12 @@ void ZSCombineElite_OnMapStart_NPC() PrecacheModel("models/combine_super_soldier.mdl"); PrecacheModel("models/effects/combineball.mdl"); NPCData data; - strcopy(data.Name, sizeof(data.Name), "Infected Elite"); + strcopy(data.Name, sizeof(data.Name), "Bandit Elite"); strcopy(data.Plugin, sizeof(data.Plugin), "npc_zs_combine_soldier_elite"); strcopy(data.Icon, sizeof(data.Icon), "combine_elite"); data.IconCustom = true; data.Flags = 0; - data.Category = Type_Common; + data.Category = Type_GmodZS; data.Func = ClotSummon; NPC_Add(data); } @@ -155,7 +155,8 @@ methodmap ZSCombineElite < CClotBody public ZSCombineElite(float vecPos[3], float vecAng[3], int ally) { - ZSCombineElite npc = view_as(CClotBody(vecPos, vecAng, "models/combine_super_soldier.mdl", "1.15", "1500", ally)); + ally = TFTeam_Stalkers; + ZSCombineElite npc = view_as(CClotBody(vecPos, vecAng, "models/combine_super_soldier.mdl", "1.15", "10000", ally)); i_NpcWeight[npc.index] = 1; @@ -171,15 +172,26 @@ methodmap ZSCombineElite < CClotBody func_NPCDeath[npc.index] = ZSCombineElite_NPCDeath; func_NPCOnTakeDamage[npc.index] = ZSCombineElite_OnTakeDamage; func_NPCThink[npc.index] = ZSCombineElite_ClotThink; + + for(int client_check=1; client_check<=MaxClients; client_check++) + { + if(IsClientInGame(client_check) && !IsFakeClient(client_check)) + { + ShowGameText(client_check, "voice_player", 1, "%t", "Bandits Spawned"); + } + } npc.m_fbGunout = false; + AddNpcToAliveList(npc.index, 1); + TeleportDiversioToRandLocation(npc.index,_,1750.0, 1250.0); npc.m_iState = 0; - npc.m_flSpeed = 260.0; + npc.m_flSpeed = 330.0; npc.m_flNextRangedAttack = 0.0; npc.m_flNextRangedSpecialAttack = 0.0; npc.m_flAttackHappenswillhappen = false; npc.m_bmovedelay = false; + AddNpcToAliveList(npc.index, 1); npc.m_iAttacksTillReload = 30; @@ -246,7 +258,7 @@ public void ZSCombineElite_ClotThink(int iNPC) else if (bInMeleeRange) { // 근접 추격 모드 - npc.m_flSpeed = 260.0; + npc.m_flSpeed = 330.0; npc.StartPathing(); npc.SetGoalEntity(PrimaryThreatIndex); npc.m_fbGunout = false; @@ -296,7 +308,7 @@ public void ZSCombineElite_ClotThink(int iNPC) else { // 원거리 추격 모드 - npc.m_flSpeed = 260.0; + npc.m_flSpeed = 330.0; npc.StartPathing(); npc.SetGoalEntity(PrimaryThreatIndex); npc.m_fbGunout = false; @@ -333,7 +345,7 @@ public void ZSCombineElite_ClotThink(int iNPC) int target = TR_GetEntityIndex(swingTrace); if(target > 0) { - SDKHooks_TakeDamage(target, npc.index, npc.index, 60.0, DMG_CLUB, -1, _, vecTarget); + SDKHooks_TakeDamage(target, npc.index, npc.index, 200.0, DMG_CLUB, -1, _, vecTarget); Custom_Knockback(npc.index, target, 250.0); npc.PlayMeleeHitSound(); } @@ -356,8 +368,10 @@ public void ZSCombineElite_ClotThink(int iNPC) if(npc.m_flNextRangedSpecialAttack < GetGameTime(npc.index)) { float vPredictedPos[3]; PredictSubjectPosition(npc, PrimaryThreatIndex,_,_, vPredictedPos); - npc.FireRocket(vPredictedPos, 15.0, 400.0, "models/effects/combineball.mdl"); - npc.m_flNextRangedSpecialAttack = GetGameTime(npc.index) + 9.0; + int projectile = npc.FireParticleRocket(vPredictedPos, 3000.0, 400.0, 150.0, "burningplayer_blueglow", true); + SDKUnhook(projectile, SDKHook_StartTouch, Rocket_Particle_StartTouch); + SDKHook(projectile, SDKHook_StartTouch, Combine_Rocket_Particle_StartTouch); + npc.m_flNextRangedSpecialAttack = GetGameTime(npc.index) + 10.0; npc.PlayRangedAttackSecondarySound(); } @@ -395,7 +409,7 @@ public void ZSCombineElite_ClotThink(int iNPC) vecDir[2] = vecDirShooting[2] + x * 0.1 * vecRight[2] + y * 0.1 * vecUp[2]; NormalizeVector(vecDir, vecDir); - FireBullet(npc.index, npc.m_iWearable1, SelfVecPos, vecDir, 10.0, 9000.0, DMG_BULLET, "bullet_tracer01_red"); + FireBullet(npc.index, npc.m_iWearable1, SelfVecPos, vecDir, 30.0, 9000.0, DMG_BULLET, "bullet_tracer01_red"); npc.PlayRangedSound(); } } @@ -429,6 +443,44 @@ public Action ZSCombineElite_OnTakeDamage(int victim, int &attacker, int &inflic return Plugin_Changed; } +public void Combine_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); + + if(b_should_explode[entity]) //should we "explode" or do "kinetic" damage + { + SDKHooks_TakeDamage(target, owner, inflictor, 500.0, DMG_TRUEDAMAGE, -1); //acts like a kinetic rocket + } + + } + else + { + int particle = EntRefToEntIndex(i_WandParticle[entity]); + //we uhh, missed? + if(IsValidEntity(particle)) + { + RemoveEntity(particle); + } + } + RemoveEntity(entity); +} + public void ZSCombineElite_NPCDeath(int entity) { ZSCombineElite npc = view_as(entity); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_eradicator.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_eradicator.sp index b5deb086d0..f149da054e 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_eradicator.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_eradicator.sp @@ -105,7 +105,7 @@ methodmap Eradicator < CClotBody public Eradicator(float vecPos[3], float vecAng[3], int ally) { - Eradicator npc = view_as(CClotBody(vecPos, vecAng, "models/zombie_riot/gmod_zs/zs_zombie_models_1_1.mdl", "1.15", "30000", ally, false)); + Eradicator npc = view_as(CClotBody(vecPos, vecAng, "models/zombie_riot/gmod_zs/zs_zombie_models_1_1.mdl", "1.15", "70000", ally, false)); i_NpcWeight[npc.index] = 1; @@ -222,7 +222,7 @@ public void Eradicator_ClotThink(int iNPC) { { if(!ShouldNpcDealBonusDamage(target)) - SDKHooks_TakeDamage(target, npc.index, npc.index, 175.0, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, 200.0, DMG_CLUB, -1, _, vecHit); else SDKHooks_TakeDamage(target, npc.index, npc.index, 500.0, DMG_CLUB, -1, _, vecHit); } diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_firefighter.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_firefighter.sp index 24736c9797..c1b685974a 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_firefighter.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_firefighter.sp @@ -293,7 +293,7 @@ public void InfectedFireFighter_ClotThink(int iNPC) if(!ShouldNpcDealBonusDamage(target)) { - SDKHooks_TakeDamage(target, npc.index, npc.index, 150.0, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, 175.0, DMG_CLUB, -1, _, vecHit); // TF2_IgnitePlayer(target, npc.index, 5.0); } else diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_ihbc.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_ihbc.sp index dcc6e6875c..4f800c1f8a 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_ihbc.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_ihbc.sp @@ -26,7 +26,7 @@ void InfectedHazardous_OnMapStart_NPC() strcopy(data.Icon, sizeof(data.Icon), "medic_main"); data.IconCustom = true; data.Flags = 0; - data.Category = Type_Common; + data.Category = Type_GmodZS; data.Func = ClotSummon; NPC_Add(data); } @@ -89,7 +89,7 @@ methodmap InfectedHazardous < CClotBody public InfectedHazardous(float vecPos[3], float vecAng[3], int ally) { - InfectedHazardous npc = view_as(CClotBody(vecPos, vecAng, "models/player/medic.mdl", "1.0", "25000", ally)); + InfectedHazardous npc = view_as(CClotBody(vecPos, vecAng, "models/player/medic.mdl", "1.0", "45000", ally)); i_NpcWeight[npc.index] = 1; @@ -251,16 +251,16 @@ public void InfectedHazardous_ClotThink(int iNPC) { if(!ShouldNpcDealBonusDamage(target)) - SDKHooks_TakeDamage(target, npc.index, npc.index, 100.0, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, 175.0, DMG_CLUB, -1, _, vecHit); else - SDKHooks_TakeDamage(target, npc.index, npc.index, 550.0, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, 500.0, DMG_CLUB, -1, _, vecHit); Elemental_AddPheromoneDamage(target, npc.index, npc.index ? 30 : 10); int flagsStun = 0; if(!HasSpecificBuff(target, "Fluid Movement")) flagsStun |= TF_STUNFLAG_SLOWDOWN; if(target <= MaxClients) - TF2_StunPlayer(target, 2.0, 0.5, flagsStun); + TF2_StunPlayer(target, 2.0, 0.9, flagsStun); ApplyStatusEffect(npc.index, target, "Cellular Breakdown", 8.0); // Hit sound npc.PlayMeleeHitSound(); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_manhattan_parrot.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_manhattan_parrot.sp new file mode 100644 index 0000000000..571c35431e --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_manhattan_parrot.sp @@ -0,0 +1,383 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_HurtSounds[][] = { + "vo/demoman_painsharp01.mp3", + "vo/demoman_painsharp02.mp3", + "vo/demoman_painsharp03.mp3", + "vo/demoman_painsharp04.mp3", + "vo/demoman_painsharp05.mp3", + "vo/demoman_painsharp06.mp3", + "vo/demoman_painsharp07.mp3", +}; + +static const char g_IdleAlertedSounds[][] = { + "weapons/demo_charge_windup1.wav", + "weapons/demo_charge_windup2.wav", + "weapons/demo_charge_windup3.wav", +}; + +static const char g_MeleeHitSounds[][] = { + "weapons/boxing_gloves_hit1.wav", + "weapons/boxing_gloves_hit2.wav", + "weapons/boxing_gloves_hit3.wav", + "weapons/boxing_gloves_hit4.wav", +}; + +void ManhattanParrot_OnMapStart_NPC() +{ + 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_MeleeHitSounds)); i++) { PrecacheSound(g_MeleeHitSounds[i]); } + + + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Manhattan Parrot"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_zs_manhattan_parrot"); + strcopy(data.Icon, sizeof(data.Icon), "demo"); + data.IconCustom = false; + data.Flags = 0; + data.Category = Type_GmodZS; + data.Func = ClotSummon; + NPC_Add(data); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return ManhattanParrot(vecPos, vecAng, team); +} +methodmap ManhattanParrot < CClotBody +{ + public void PlayIdleAlertSound() { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(2.0, 3.0); + + + } + public void PlayMeleeHitSound() { + EmitSoundToAll(g_MeleeHitSounds[GetRandomInt(0, sizeof(g_MeleeHitSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, GetRandomInt(80, 100)); + + + } + + 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_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + + } + public ManhattanParrot(float vecPos[3], float vecAng[3], int ally) + { + ManhattanParrot npc = view_as(CClotBody(vecPos, vecAng, "models/player/demo.mdl", "1.0", "6000", ally)); + + i_NpcWeight[npc.index] = 1; + + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_MP_RUN_MELEE"); + if(iActivity > 0) npc.StartActivity(iActivity); + + npc.m_bDissapearOnDeath = true; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + npc.m_flGetClosestTargetTime = 0.0; + npc.StartPathing(); + + func_NPCDeath[npc.index] = ManhattanParrot_NPCDeath; + func_NPCOnTakeDamage[npc.index] = ManhattanParrot_OnTakeDamage; + func_NPCThink[npc.index] = ManhattanParrot_ClotThink; + + npc.m_flMeleeArmor = 3.0; + npc.Anger = false; + + int skin = 1; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable1 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_caber/c_caber.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + + npc.m_iWearable2 = npc.EquipItem("head", "models/workshop/player/items/demo/hw2013_manbird_of_aberdeen/hw2013_manbird_of_aberdeen.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable2, "SetModelScale"); + + npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/player/items/demo/sf14_explosive_mind/sf14_explosive_mind.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable3, "SetModelScale"); + + npc.m_iWearable4 = npc.EquipItem("head", "models/workshop/player/items/demo/demo_dynamite/demo_dynamite.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable4, "SetModelScale"); + + npc.m_iWearable5 = npc.EquipItem("head", "models/workshop/player/items/demo/hwn2016_aerobatics_demonstrator/hwn2016_aerobatics_demonstrator.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable5, "SetModelScale"); + + npc.m_iWearable6 = npc.EquipItem("head", "models/workshop/player/items/demo/demo_booties/demo_booties.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable6, "SetModelScale"); + + 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); + + npc.m_flSpeed = 280.0; + npc.StartPathing(); + + return npc; + } + + +} + + +public void ManhattanParrot_ClotThink(int iNPC) +{ + ManhattanParrot npc = view_as(iNPC); + + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) + { + return; + } + + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + float gameTime = GetGameTime(npc.index); + npc.Update(); + + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + if(!npc.Anger) + { + if(npc.m_flNextThinkTime > gameTime) + return; + } + else + { + if(npc.m_flNextThinkTime > GetGameTime()) + return; + } + if(npc.Anger) + { + RemoveSpecificBuff(npc.index, "Unstoppable Force"); + SDKHooks_TakeDamage(npc.index, 0, 0, 200.0, DMG_BLAST); + SmiteNpcToDeath(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(); + } + + int PrimaryThreatIndex = npc.m_iTarget; + + if(IsValidEnemy(npc.index, PrimaryThreatIndex)) + { + float vecTarget[3]; WorldSpaceCenter(PrimaryThreatIndex, vecTarget); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + + //Predict their pos. + if(flDistanceToTarget < npc.GetLeadRadius()) { + + float vPredictedPos[3]; PredictSubjectPosition(npc, PrimaryThreatIndex,_,_, vPredictedPos); + + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(PrimaryThreatIndex); + } + npc.StartPathing(); + + if(flDistanceToTarget < NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED || npc.m_flAttackHappenswillhappen) + { + //Look at target so we hit. + // npc.FaceTowards(vecTarget, 1000.0); + + //Can we attack right now? + if(npc.m_flNextMeleeAttack < GetGameTime(npc.index)) + { + //Play attack ani + if (!npc.m_flAttackHappenswillhappen) + { + npc.AddGesture("ACT_MP_ATTACK_STAND_MELEE"); + npc.m_flAttackHappens = GetGameTime(npc.index)+0.4; + npc.m_flAttackHappens_bullshit = GetGameTime(npc.index)+0.54; + npc.m_flAttackHappenswillhappen = true; + } + + if (npc.m_flAttackHappens < GetGameTime(npc.index) && npc.m_flAttackHappens_bullshit >= GetGameTime(npc.index) && npc.m_flAttackHappenswillhappen) + { + Handle swingTrace; + npc.FaceTowards(vecTarget, 20000.0); + if(npc.DoSwingTrace(swingTrace, PrimaryThreatIndex)) + { + int target = TR_GetEntityIndex(swingTrace); + + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + + if(target > 0) + { + + if(!ShouldNpcDealBonusDamage(target)) + SDKHooks_TakeDamage(target, npc.index, npc.index, 200.0, DMG_CLUB, -1, _, vecHit); + else + SDKHooks_TakeDamage(target, npc.index, npc.index, 400.0, DMG_CLUB, -1, _, vecHit); + + float startPosition[3]; + GetEntPropVector(target, Prop_Data, "m_vecAbsOrigin", startPosition); + makeexplosion(-1, startPosition, 0, 0 , 0); + + // Hit sound + npc.PlayMeleeHitSound(); + + } + } + delete swingTrace; + npc.m_flNextMeleeAttack = GetGameTime(npc.index) + 0.8; + npc.m_flAttackHappenswillhappen = false; + } + else if (npc.m_flAttackHappens_bullshit < GetGameTime(npc.index) && npc.m_flAttackHappenswillhappen) + { + npc.m_flAttackHappenswillhappen = false; + npc.m_flNextMeleeAttack = GetGameTime(npc.index) + 0.8; + } + } + } + else + { + npc.StartPathing(); + + } + } + else + { + npc.StopPathing(); + + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleAlertSound(); +} +static void ManhattanParrot_DownedThink(int entity) +{ + ManhattanParrot npc = view_as(entity); + npc.SetActivity("ACT_MP_STUN_MIDDLE"); + npc.AddGesture("ACT_MP_STUN_BEGIN"); + npc.Update(); + func_NPCThink[npc.index] = ManhattanParrot_ClotThink; +} +public Action ManhattanParrot_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + //Valid attackers only. + if(attacker <= 0) + return Plugin_Continue; + + ManhattanParrot npc = view_as(victim); + + if(!npc.Anger && damage >= GetEntProp(npc.index, Prop_Data, "m_iHealth")) + { + SetEntProp(npc.index, Prop_Data, "m_iHealth", 1); + ApplyStatusEffect(npc.index, npc.index, "Unstoppable Force", 3.0); + + npc.Anger = true; + npc.PlayHurtSound(); + npc.StopPathing(); + npc.m_flNextThinkTime = GetGameTime() + 2.0; + + func_NPCThink[npc.index] = ManhattanParrot_DownedThink; + + float vecMe[3]; WorldSpaceCenter(npc.index, vecMe); + spawnRing_Vectors(vecMe, 200.0 * 2.0, 0.0, 0.0, 5.0, "materials/sprites/laserbeam.vmt", 0, 0, 212, 255, 1, 1.95, 5.0, 0.0, 1); + spawnRing_Vectors(vecMe, 0.0, 0.0, 0.0, 5.0, "materials/sprites/laserbeam.vmt", 0, 0, 212, 255, 1, 1.95, 5.0, 0.0, 1, 200.0 * 2.0); + + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + + damage = 0.0; + return Plugin_Handled; + } + + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + + return Plugin_Changed; +} + +public void ManhattanParrot_NPCDeath(int entity) +{ + ManhattanParrot npc = view_as(entity); + float vecMe[3]; WorldSpaceCenter(npc.index, vecMe); + if(!NpcStats_IsEnemySilenced(entity)) + { + float startPosition[3]; + GetEntPropVector(entity, Prop_Data, "m_vecAbsOrigin", startPosition); + startPosition[2] += 45; + /* + DataPack pack; + pack.WriteCell(entity); + pack.WriteFloat(startPosition[0]); + pack.WriteFloat(startPosition[1]); + pack.WriteFloat(startPosition[2]); + pack.WriteCell(100); + pack.WriteCell(100); + RequestFrame(DelayExplosiveMakeExplosion, pack); + */ + makeexplosion(entity, startPosition, 65, 200, _, true); + } + else + { + npc.m_bDissapearOnDeath = false; + } + + TE_Particle("asplode_hoodoo", vecMe, NULL_VECTOR, NULL_VECTOR, _, _, _, _, _, _, _, _, _, _, 0.0); + + b_NpcIsTeamkiller[npc.index] = true; + Explode_Logic_Custom(200.0, npc.index, npc.index, -1, vecMe, 200.0, 1.0, _, true, 40, _, _, _); + b_NpcIsTeamkiller[npc.index] = false; + + + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); + if(IsValidEntity(npc.m_iWearable5)) + RemoveEntity(npc.m_iWearable5); + if(IsValidEntity(npc.m_iWearable6)) + RemoveEntity(npc.m_iWearable6); + if(IsValidEntity(npc.m_iWearable7)) + RemoveEntity(npc.m_iWearable7); +} + diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_medic_main.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_medic_main.sp index e54edbacad..896143cd36 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_medic_main.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_medic_main.sp @@ -57,7 +57,7 @@ void InfectedBattleMedic_OnMapStart_NPC() data.IconCustom = true; data.Flags = 0; data.Precache = ClotPrecache; - data.Category = Type_Common; + data.Category = Type_GmodZS; data.Func = ClotSummon; NPC_Add(data); } @@ -131,7 +131,7 @@ methodmap InfectedBattleMedic < CClotBody public InfectedBattleMedic(float vecPos[3], float vecAng[3], int ally) { - InfectedBattleMedic npc = view_as(CClotBody(vecPos, vecAng, "models/player/medic.mdl", "1.0", "25000", ally)); + InfectedBattleMedic npc = view_as(CClotBody(vecPos, vecAng, "models/player/medic.mdl", "1.0", "40000", ally)); i_NpcWeight[npc.index] = 1; @@ -456,7 +456,7 @@ static int InfectedBattleMedic_Work(InfectedBattleMedic npc, float gameTime, flo if(IsValidEnemy(npc.index, target)) { - float damageDealt = 100.0; + float damageDealt = 175.0; if(ShouldNpcDealBonusDamage(target)) damageDealt*=3.0; SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_CLUB, -1, _, vecHit); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_mlsm.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_mlsm.sp index 802cb86cf3..a7948f66e9 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_mlsm.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_mlsm.sp @@ -98,7 +98,7 @@ methodmap MassShootingLover < CClotBody public MassShootingLover(float vecPos[3], float vecAng[3], int ally) { - MassShootingLover npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "40000", ally)); + MassShootingLover npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "50000", ally)); i_NpcWeight[npc.index] = 1; FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); @@ -122,7 +122,7 @@ methodmap MassShootingLover < CClotBody npc.m_iOverlordComboAttack = 10; npc.StartPathing(); - npc.m_flSpeed = 250.0; + npc.m_flSpeed = 300.0; int skin = 5; SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); @@ -315,6 +315,7 @@ void MassShootingLoverSelfDefense(MassShootingLover npc, float gameTime) SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_BULLET, -1, _, vecHit); + IncreaseEntityDamageTakenBy(target, 0.1, 3.5, true); } } delete swingTrace; diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_sam.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_sam.sp index bf9e9b0d90..2e21d5f064 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_sam.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_sam.sp @@ -107,12 +107,9 @@ methodmap StoneAgeMaker < CClotBody func_NPCOnTakeDamage[npc.index] = view_as(StoneAgeMaker_OnTakeDamage); func_NPCThink[npc.index] = view_as(StoneAgeMaker_ClotThink); - - npc.StartPathing(); npc.m_flSpeed = 210.0; - int skin = 5; SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); @@ -291,7 +288,7 @@ int StoneAgeMakerSelfDefense(StoneAgeMaker npc, float gameTime, float distance) //Direct mode if(gameTime > npc.m_flNextMeleeAttack) { - if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 10.0)) + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 20.0)) { float VecAim[3]; WorldSpaceCenter(npc.m_iTarget, VecAim ); npc.FaceTowards(VecAim, 20000.0); @@ -300,7 +297,7 @@ int StoneAgeMakerSelfDefense(StoneAgeMaker npc, float gameTime, float distance) { npc.m_iTarget = Enemy_I_See; npc.PlayMeleeSound(); - float RocketDamage = 135.0; + float RocketDamage = 200.0; float RocketSpeed = 500.0; float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); float VecStart[3]; WorldSpaceCenter(npc.index, VecStart ); @@ -339,7 +336,7 @@ int StoneAgeMakerSelfDefense(StoneAgeMaker npc, float gameTime, float distance) } //No can shooty. //Enemy is close enough. - if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 9.0)) + if(distance < (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 18.0)) { if(Can_I_See_Enemy_Only(npc.index, npc.m_iTarget)) { diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_soldier_messenger.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_soldier_messenger.sp index 7c51c9d56f..1c79fb1558 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_soldier_messenger.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_soldier_messenger.sp @@ -134,7 +134,7 @@ methodmap InfectedMessenger < CClotBody public InfectedMessenger(float vecPos[3], float vecAng[3], int ally) { - InfectedMessenger npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "70000", ally)); + InfectedMessenger npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "100000", ally)); SetVariantInt(2); AcceptEntityInput(npc.index, "SetBodyGroup"); @@ -166,7 +166,6 @@ methodmap InfectedMessenger < CClotBody g_infected_messenger_died=false; g_infected_messenger_die=0.0; AddNpcToAliveList(npc.index, 1); - npc.m_bStaticNPC = true; b_ThisNpcIsImmuneToNuke[npc.index] = true; b_ThisEntityIgnoredByOtherNpcsAggro[npc.index] = true; @@ -394,7 +393,7 @@ public Action InfectedMessenger_OnTakeDamage(int victim, int &attacker, int &inf npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; npc.m_blPlayHurtAnimation = true; } - if((ReturnEntityMaxHealth(npc.index)/4) >= GetEntProp(npc.index, Prop_Data, "m_iHealth") && !npc.Anger) + if((ReturnEntityMaxHealth(npc.index)/2) >= GetEntProp(npc.index, Prop_Data, "m_iHealth") && !npc.Anger) { npc.Anger = true; if(!npc.m_bAlliesSummoned) diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_stranger.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_stranger.sp index 0be9744f1c..d9d4bfec51 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_stranger.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_stranger.sp @@ -56,7 +56,7 @@ void StrangPyro_OnMapStart_NPC() strcopy(data.Icon, sizeof(data.Icon), "pyro"); data.IconCustom = false; data.Flags = MVM_CLASS_FLAG_MINIBOSS; - data.Category = Type_Common; + data.Category = Type_GmodZS; data.Func = ClotSummon; NPC_Add(data); } @@ -125,7 +125,7 @@ methodmap StrangPyro < CClotBody public StrangPyro(float vecPos[3], float vecAng[3], int ally) { - StrangPyro npc = view_as(CClotBody(vecPos, vecAng, "models/player/pyro.mdl", "1.35", "75000", ally, false, true)); + StrangPyro npc = view_as(CClotBody(vecPos, vecAng, "models/player/pyro.mdl", "1.35", "200000", ally, false, true)); i_NpcWeight[npc.index] = 3; SetVariantInt(1); @@ -384,7 +384,7 @@ void StrangerPyroSelfDefense(StrangPyro npc, float gameTime, int target, float d if(ShouldNpcDealBonusDamage(target)) damageDealt *= 2.0; - SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_TRUEDAMAGE, -1, _, vecHit); // Hit sound } diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_vile_poisonheadcrab_zombie.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_vile_poisonheadcrab_zombie.sp index db593d489d..8eef38e169 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_vile_poisonheadcrab_zombie.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_vile_poisonheadcrab_zombie.sp @@ -125,7 +125,7 @@ methodmap ZSVILEPoisonheadcrabZombie < CClotBody public ZSVILEPoisonheadcrabZombie(float vecPos[3], float vecAng[3], int ally) { - ZSVILEPoisonheadcrabZombie npc = view_as(CClotBody(vecPos, vecAng, "models/zombie/poison.mdl", "1.15", "60000", ally)); + ZSVILEPoisonheadcrabZombie npc = view_as(CClotBody(vecPos, vecAng, "models/zombie/poison.mdl", "1.15", "80000", ally)); i_NpcWeight[npc.index] = 2; @@ -147,7 +147,7 @@ methodmap ZSVILEPoisonheadcrabZombie < CClotBody //IDLE npc.m_flAttackHappenswillhappen = false; - npc.m_flSpeed = 260.0; + npc.m_flSpeed = 300.0; npc.StartPathing(); SetEntityRenderMode(npc.index, RENDER_TRANSCOLOR); @@ -259,10 +259,10 @@ public void ZSVILEPoisonheadcrabZombie_ClotThink(int iNPC) { { if(!ShouldNpcDealBonusDamage(target)) - SDKHooks_TakeDamage(target, npc.index, npc.index, 380.0, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, 400.0, DMG_CLUB, -1, _, vecHit); else - SDKHooks_TakeDamage(target, npc.index, npc.index, 720.0, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, 1000.0, DMG_CLUB, -1, _, vecHit); Elemental_AddPheromoneDamage(target, npc.index, npc.index ? 50 : 10); } @@ -360,8 +360,8 @@ public Action ZSVILEPoisonheadcrabZombie_Revert_Poison_Zombie_Resistance(Handle int zombie = EntRefToEntIndex(ref); if(IsValidEntity(zombie)) { - SetEntityRenderMode(zombie, RENDER_NORMAL); - SetEntityRenderColor(zombie, 255, 255, 255, 255); + SetEntityRenderMode(zombie, RENDER_TRANSCOLOR); + SetEntityRenderColor(zombie, 150, 255, 150, 255); } return Plugin_Handled; } diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_breadmonster.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_breadmonster.sp index a89f7f1901..67fc379cf7 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_breadmonster.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_breadmonster.sp @@ -86,7 +86,7 @@ methodmap BreadMonster < CClotBody public BreadMonster(float vecPos[3], float vecAng[3], int ally) { - BreadMonster npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "30000", ally)); + BreadMonster npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "50000", ally)); i_NpcWeight[npc.index] = 2; npc.SetActivity("ACT_MP_RUN_MELEE"); @@ -242,7 +242,7 @@ void BreadMonster_OnTakeDamage(int victim, int &attacker, int &inflictor, float npc.flXenoInfectedSpecialHurtTime = GetGameTime(npc.index) + 2.0; SetEntityRenderMode(npc.index, RENDER_NORMAL); SetEntityRenderColor(npc.index, 255, 165, 0, 255); - npc.m_flSpeed = 520.0; + npc.m_flSpeed = 550.0; CreateTimer(2.0, BreadMonster_Revert_Zombie_Resistance, EntIndexToEntRef(victim), TIMER_FLAG_NO_MAPCHANGE); CreateTimer(10.0, BreadMonster_Revert_Zombie_Resistance_Enable, EntIndexToEntRef(victim), TIMER_FLAG_NO_MAPCHANGE); } @@ -265,7 +265,7 @@ public Action BreadMonster_Revert_Zombie_Resistance(Handle timer, int ref) if(IsValidEntity(zombie)) { BreadMonster npc = view_as(zombie); - npc.m_flSpeed = 260.0; + npc.m_flSpeed = 299.0; SetEntityRenderMode(zombie, RENDER_NORMAL); SetEntityRenderColor(zombie, 255, 255, 255, 255); } diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_fatscout.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_fatscout.sp index 07cfe04437..142cba2158 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_fatscout.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_fatscout.sp @@ -67,7 +67,7 @@ methodmap InfectedFatScout < CClotBody public InfectedFatScout(float vecPos[3], float vecAng[3], int ally, const char[] data) { - InfectedFatScout npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "30000", ally)); + InfectedFatScout npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "60000", ally)); i_NpcWeight[npc.index] = 2; int iActivity = npc.LookupActivity("ACT_MP_RUN_SECONDARY"); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_fatspy.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_fatspy.sp index 02ebea2b2d..23b26dc6fc 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_fatspy.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_zombie_fatspy.sp @@ -86,7 +86,7 @@ methodmap InfectedFatSpy < CClotBody public InfectedFatSpy(float vecPos[3], float vecAng[3], int ally) { - InfectedFatSpy npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "30000", ally)); + InfectedFatSpy npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "50000", ally)); i_NpcWeight[npc.index] = 2; int iActivity = npc.LookupActivity("ACT_MP_RUN_MELEE_ALLCLASS"); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_doctor_unclean_one.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_doctor_unclean_one.sp index 98c6cfbab4..bc2593ec6a 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_doctor_unclean_one.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_doctor_unclean_one.sp @@ -231,8 +231,9 @@ methodmap DasNaggenvatcher < CClotBody i_ClosestAllyCDTarget[npc.index] = 0.0; g_dasnaggenvatcher_died=false; g_dasnaggenvatcher_die=0.0; + WaveStart_SubWaveStart(GetGameTime() + 1000.0); - RaidModeTime = GetGameTime(npc.index) + 300.0; + RaidModeTime = GetGameTime(npc.index) + 400.0; RaidBossActive = EntIndexToEntRef(npc.index); RaidAllowsBuildings = true; npc.Anger = false; @@ -610,6 +611,7 @@ public void DasNaggenvatcher_ClotThink(int iNPC) if(!npc.m_fbGunout) { npc.m_fbGunout = true; + RaidModeTime += 10.0; switch(GetRandomInt(0,3)) { case 0: @@ -806,6 +808,7 @@ public Action DasNaggenvatcher_OnTakeDamage(int victim, int &attacker, int &infl if(EntRefToEntIndex(RaidBossActive)==npc.index) RaidBossActive = INVALID_ENT_REFERENCE; g_dasnaggenvatcher_die = GetGameTime(npc.index) + 40.0; + RaidModeTime += 60.0; SetEntProp(npc.index, Prop_Data, "m_iHealth", 1); damage = 0.0; @@ -824,13 +827,17 @@ public void DasNaggenvatcher_OnTakeDamagePost(int victim, int attacker, int infl npc.g_TimesSummoned = 1; npc.PlaySummonSound(); npc.m_flDoingSpecial = GetGameTime(npc.index) + 10.0; + RaidModeTime += 30.0; - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_soldier_pickaxe",22000, RoundToCeil(6.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_soldier",20000, RoundToCeil(6.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_demoknight",17500, RoundToCeil(6.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_heavy",15000, RoundToCeil(4.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_engineer",12500, RoundToCeil(4.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_soldier_pickaxe",40000, RoundToCeil(6.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_soldier",30000, RoundToCeil(6.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_demoknight",25000, RoundToCeil(6.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_heavy",30000, RoundToCeil(4.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_engineer",20000, RoundToCeil(4.0 * MultiGlobalEnemy)); DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_kamikaze_demo",3000, RoundToCeil(6.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_huntsman",20000, RoundToCeil(4.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_infected_tomislav_main",20000, RoundToCeil(4.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_sniper_jarate",20000, RoundToCeil(2.0 * MultiGlobalEnemy)); DasNaggenvatcherSpawnEnemy(npc.index,"npc_random_zombie", RoundToCeil(100000.0 * MultiGlobalHighHealthBoss), 1); } else if(Ratio <= 0.55 && npc.g_TimesSummoned < 2) @@ -838,11 +845,14 @@ public void DasNaggenvatcher_OnTakeDamagePost(int victim, int attacker, int infl npc.g_TimesSummoned = 2; npc.PlaySummonSound(); npc.m_flDoingSpecial = GetGameTime(npc.index) + 10.0; + RaidModeTime += 30.0; - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_eradicator",30000, RoundToCeil(6.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_vile_poisonheadcrab_zombie",60000, RoundToCeil(6.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_eradicator",70000, RoundToCeil(6.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_vile_poisonheadcrab_zombie",80000, RoundToCeil(6.0 * MultiGlobalEnemy)); DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_fastheadcrab_zombie",30000, RoundToCeil(6.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_vile_bloated_zombie",30000, RoundToCeil(6.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_vile_bloated_zombie",50000, RoundToCeil(6.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_gore_blaster",30000, RoundToCeil(6.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_runner",30000, RoundToCeil(6.0 * MultiGlobalEnemy)); DasNaggenvatcherSpawnEnemy(npc.index,"npc_random_zombie", RoundToCeil(100000.0 * MultiGlobalHighHealthBoss), 1); } else if(Ratio <= 0.35 && npc.g_TimesSummoned < 3) @@ -850,15 +860,16 @@ public void DasNaggenvatcher_OnTakeDamagePost(int victim, int attacker, int infl npc.g_TimesSummoned = 3; npc.PlaySummonSound(); npc.m_flDoingSpecial = GetGameTime(npc.index) + 10.0; + RaidModeTime += 30.0; - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_ihbc",25000, RoundToCeil(5.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_ihbc",45000, RoundToCeil(5.0 * MultiGlobalEnemy)); DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_firefighter",50000, RoundToCeil(5.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_breadmonster",30000, RoundToCeil(5.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_fatscout",30000, RoundToCeil(5.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_fatspy",30000, RoundToCeil(2.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_breadmonster",50000, RoundToCeil(5.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_fatscout",60000, RoundToCeil(5.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_zombie_fatspy",50000, RoundToCeil(2.0 * MultiGlobalEnemy)); DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_sniper",20000, RoundToCeil(2.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_cleaner",40000, RoundToCeil(2.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_ninja_zombie_spy",25, RoundToCeil(2.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_cleaner",50000, RoundToCeil(2.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_ninja_zombie_spy",125, RoundToCeil(2.0 * MultiGlobalEnemy)); DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_malfunctioning_heavy", RoundToCeil(300000.0 * MultiGlobalHighHealthBoss), 1); } else if(Ratio <= 0.20 && npc.g_TimesSummoned < 4) @@ -867,12 +878,13 @@ public void DasNaggenvatcher_OnTakeDamagePost(int victim, int attacker, int infl DasNaggenvatcherSayWords(npc.index); npc.g_TimesSummoned = 4; npc.PlaySummonSound(); + RaidModeTime += 30.0; npc.m_flDoingSpecial = GetGameTime(npc.index) + 10.0; DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_sniper",20000, RoundToCeil(2.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_mlsm",40000, RoundToCeil(3.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_mlsm",50000, RoundToCeil(3.0 * MultiGlobalEnemy)); DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_sam",40000, RoundToCeil(3.0 * MultiGlobalEnemy)); - DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_medic_main",25000, RoundToCeil(6.0 * MultiGlobalEnemy)); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_medic_main",40000, RoundToCeil(6.0 * MultiGlobalEnemy)); DasNaggenvatcherSpawnEnemy(npc.index,"npc_major_vulture",RoundToCeil(300000.0 * MultiGlobalHighHealthBoss), 1); DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_soldier_barrager", RoundToCeil(300000.0 * MultiGlobalHighHealthBoss), 1, true); DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_flesh_creeper", RoundToCeil(300000.0 * MultiGlobalHighHealthBoss), 1, true); @@ -958,7 +970,7 @@ void DasNaggenvatcherSayWords(int entity) { case 0: { - CPrintToChatAll("{crimson}다스 고르통보호기 메딕{default}: 우리에게서 결코 도망치지 못할 것이다."); + CPrintToChatAll("{crimson}다스 고르통보호기 메딕{default}: 함께라면 어떤 적이든 처단할 수 있다!"); } case 1: { diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_major_vulture.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_major_vulture.sp index c5793f4046..2492c9d360 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_major_vulture.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_major_vulture.sp @@ -134,6 +134,8 @@ methodmap Zsvulture < CClotBody RaidAllowsBuildings = true; } + CPrintToChatAll("{green}벌쳐 소령{default}: 좋아, 다 덤벼."); + int skin = 5; SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); npc.m_iWearable1 = npc.EquipItem("head", "models/workshop_partner/weapons/c_models/c_ai_flamethrower/c_ai_flamethrower.mdl"); @@ -344,6 +346,7 @@ public void Zsvulture_NPCDeath(int entity) { npc.PlayDeathSound(); } + CPrintToChatAll("{green}벌쳐 소령{default}: 여기가 끝이군."); if(IsValidEntity(npc.m_iWearable7)) RemoveEntity(npc.m_iWearable7); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_nightmare.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_nightmare.sp index fdfd944d8f..d8cc1450c9 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_nightmare.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_nightmare.sp @@ -134,10 +134,7 @@ methodmap ZSNightmare < CClotBody { if(IsClientInGame(client_check) && !IsFakeClient(client_check)) { - LookAtTarget(client_check, npc.index); - SetGlobalTransTarget(client_check); ShowGameText(client_check, "voice_player", 1, "%t", "Nightmare Spawned"); - UTIL_ScreenFade(client_check, 180, 1, FFADE_OUT, 0, 0, 0, 255); } } diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_pregnant.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_pregnant.sp index 23e40961d6..2a86628617 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_pregnant.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_pregnant.sp @@ -121,10 +121,7 @@ methodmap Pregnant < CClotBody { if(IsClientInGame(client_check) && !IsFakeClient(client_check)) { - LookAtTarget(client_check, npc.index); - SetGlobalTransTarget(client_check); ShowGameText(client_check, "voice_player", 1, "%t", "Pregnant Spawned"); - UTIL_ScreenFade(client_check, 180, 1, FFADE_OUT, 0, 0, 0, 255); } } @@ -196,7 +193,7 @@ public void Pregnant_ClotThink(int iNPC) if(target > 0) { npc.PlayMeleeHitSound(); - SDKHooks_TakeDamage(target, npc.index, npc.index, ShouldNpcDealBonusDamage(target) ? 1200.0 : 1000.0, DMG_CLUB); + SDKHooks_TakeDamage(target, npc.index, npc.index, ShouldNpcDealBonusDamage(target) ? 2500.0 : 1000.0, DMG_CLUB); Elemental_AddPheromoneDamage(target, npc.index, npc.index ? 200 : 100); // 800 x 0.5 @@ -239,11 +236,11 @@ public void Pregnant_ClotThink(int iNPC) npc.PlayIdleSound(); } -void Pregnant_OnTakeDamage(int victim, int attacker) +void Pregnant_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) { + Pregnant npc = view_as(victim); if(attacker > 0) { - Pregnant npc = view_as(victim); if(npc.m_flHeadshotCooldown < GetGameTime(npc.index)) { npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; @@ -257,8 +254,54 @@ void Pregnant_OnTakeDamage(int victim, int attacker) } } } + if(!NpcStats_IsEnemySilenced(victim)) + { + if(!npc.bXenoInfectedSpecialHurt) + { + npc.bXenoInfectedSpecialHurt = true; + npc.flXenoInfectedSpecialHurtTime = GetGameTime(npc.index) + 2.0; + SetEntityRenderMode(npc.index, RENDER_TRANSCOLOR); + SetEntityRenderColor(npc.index, 150, 255, 150, 65); + CreateTimer(2.0, Pregnant_Revert_Poison_Zombie_Resistance, EntIndexToEntRef(victim), TIMER_FLAG_NO_MAPCHANGE); + CreateTimer(10.0, Pregnant_Revert_Poison_Zombie_Resistance_Enable, EntIndexToEntRef(victim), TIMER_FLAG_NO_MAPCHANGE); + } + float TrueArmor = 1.0; + if(!NpcStats_IsEnemySilenced(victim)) + { + if(fl_TotalArmor[npc.index] == 1.0) + { + if(npc.flXenoInfectedSpecialHurtTime > GetGameTime(npc.index)) + { + TrueArmor *= 0.25; + fl_TotalArmor[npc.index] = TrueArmor; + OnTakeDamageNpcBaseArmorLogic(victim, attacker, damage, damagetype, true); + } + } + } + fl_TotalArmor[npc.index] = TrueArmor; + } +} +public Action Pregnant_Revert_Poison_Zombie_Resistance(Handle timer, int ref) +{ + int zombie = EntRefToEntIndex(ref); + if(IsValidEntity(zombie)) + { + SetEntityRenderMode(zombie, RENDER_NORMAL); + SetEntityRenderColor(zombie, 255, 255, 255, 255); + } + return Plugin_Handled; } +public Action Pregnant_Revert_Poison_Zombie_Resistance_Enable(Handle timer, int ref) +{ + int zombie = EntRefToEntIndex(ref); + if(IsValidEntity(zombie)) + { + Pregnant npc = view_as(zombie); + npc.bXenoInfectedSpecialHurt = false; + } + return Plugin_Handled; +} void Pregnant_NPCDeath(int entityy) { Pregnant npc = view_as(entityy); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_soldier_barrager.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_soldier_barrager.sp index 57235798cc..a27b3548af 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_soldier_barrager.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_soldier_barrager.sp @@ -149,6 +149,22 @@ methodmap ZsSoldier_Barrager < CClotBody RaidAllowsBuildings = true; } + switch(GetRandomInt(0,2)) + { + case 0: + { + CPrintToChatAll("{green}탄막 대령{default}: 형님 나가신다!"); + } + case 1: + { + CPrintToChatAll("{green}탄막 대령{default}: 드디어 시작이군!"); + } + case 2: + { + CPrintToChatAll("{green}탄막 대령{default}: 힘 좀 써 볼까!"); + } + } + //IDLE npc.m_flSpeed = 270.0; @@ -292,7 +308,7 @@ static void Internal_ClotThink(int iNPC) if(npc.m_iAmmo <= 0 || b_we_are_reloading[npc.index]) { npc.StartPathing(); - npc.m_flSpeed = 400.0; + npc.m_flSpeed = 270.0; int Enemy_I_See = Can_I_See_Enemy(npc.index, PrimaryThreatIndex); if(IsValidEnemy(npc.index, Enemy_I_See)) @@ -323,7 +339,7 @@ static void Internal_ClotThink(int iNPC) if(npc.m_flNextMeleeAttack < GameTime) { - npc.AddGesture("ACT_MP_ATTACK_STAND_PRIMARY"); + npc.AddGesture("ACT_MP_ATTACK_STAND_PRIMARY"); PredictSubjectPositionForProjectiles(npc, PrimaryThreatIndex, 750.0, _, vecTarget); npc.FaceTowards(vecTarget, 20000.0); npc.PlayMeleeSound(); @@ -365,8 +381,9 @@ static void Internal_NPCDeath(int entity) ZsSoldier_Barrager npc = view_as(entity); if(!npc.m_bGib) { - npc.PlayDeathSound(); + npc.PlayDeathSound(); } + CPrintToChatAll("{green}탄막 대령{default}: 젠장. 잘 싸웠는데."); if(IsValidEntity(npc.m_iWearable2)) RemoveEntity(npc.m_iWearable2); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_sphynx.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_sphynx.sp index 520411a046..6cb7c9d8eb 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_sphynx.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_sphynx.sp @@ -48,7 +48,7 @@ void ZSSphynx_OnMapStart_NPC() strcopy(data.Icon, sizeof(data.Icon), "gmod_zs_sphynx"); data.IconCustom = true; data.Flags = MVM_CLASS_FLAG_MINIBOSS|MVM_CLASS_FLAG_ALWAYSCRIT; - data.Category = Type_Mutation; + data.Category = Type_GmodZS; data.Func = ClotSummon; data.Precache = ClotPrecache; NPC_Add(data); @@ -128,9 +128,16 @@ methodmap ZSSphynx < CClotBody func_NPCThink[npc.index] = view_as(ZSSphynx_ClotThink); npc.StartPathing(); - npc.m_flSpeed = 275.0; + npc.m_flSpeed = 330.0; EmitSoundToAll("npc/zombie_poison/pz_alert1.wav", _, _, _, _, 1.0); EmitSoundToAll("npc/zombie_poison/pz_alert1.wav", _, _, _, _, 1.0); + for(int client_check=1; client_check<=MaxClients; client_check++) + { + if(IsClientInGame(client_check) && !IsFakeClient(client_check)) + { + ShowGameText(client_check, "voice_player", 1, "%t", "Sphynx Spawned"); + } + } npc.m_bDissapearOnDeath = false; @@ -142,6 +149,7 @@ methodmap ZSSphynx < CClotBody RaidAllowsBuildings = true; } + return npc; } } diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_unspeakable.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_unspeakable.sp index d8abe9dc0b..e55e7480a9 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_unspeakable.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bosses/npc_zs_unspeakable.sp @@ -91,7 +91,7 @@ static void ClotPrecache() PrecacheSoundArray(g_TeleportSound); PrecacheSound(g_Jump_sound); PrecacheSound(g_SuicideSound); - PrecacheSoundCustom("#zombiesurvival/void_wave/center_of_the_void_1.mp3"); + PrecacheSoundCustom("#zombiesurvival/void_wave/unspeakable_raid.mp3"); } static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team, const char[] data) @@ -306,7 +306,7 @@ methodmap ZsUnspeakable < CClotBody npc.m_flNextMeleeAttack = 0.0; - npc.m_iBleedType = BLEEDTYPE_VOID; + npc.m_iBleedType = BLEEDTYPE_NORMAL; npc.m_iStepNoiseType = STEPSOUND_GIANT; npc.m_iNpcStepVariation = STEPTYPE_TANK; npc.m_flZsUnspeakableQuake = 0.0; @@ -627,6 +627,7 @@ public void ZsUnspeakable_ClotThink(int iNPC) if(LastMann && !AlreadySaidLastmann) { AlreadySaidLastmann = true; + RaidModeTime += 10.0; switch(GetRandomInt(0,2)) { case 0: @@ -820,7 +821,7 @@ public Action ZsUnspeakable_OnTakeDamage(int victim, int &attacker, int &inflict { if(i_RaidGrantExtra[npc.index] >= 4) { - SensalGiveShield(npc.index, CountPlayersOnRed(1) * 3); + SensalGiveShield(npc.index, CountPlayersOnRed(1) * 24); } npc.g_TimesSummoned++; ApplyStatusEffect(npc.index, npc.index, "Defensive Backup", 5.0); @@ -861,48 +862,38 @@ public Action ZsUnspeakable_OnTakeDamage(int victim, int &attacker, int &inflict static void Spawn_Zombie(ZsUnspeakable npc) { - float pos[3]; GetEntPropVector(npc.index, Prop_Data, "m_vecAbsOrigin", pos); - float ang[3]; GetEntPropVector(npc.index, Prop_Data, "m_angRotation", ang); - int maxhealth = ReturnEntityMaxHealth(npc.index); - int heck; - int spawn_index; - heck= maxhealth; - maxhealth= (heck/10); - if(i_RaidGrantExtra[npc.index] >= 4) //Only spawns if the wave is 60 or beyond. - { - CPrintToChatAll("{crimson} 저것이 끔찍한 감염체들을 소환했다.", NpcStats_ReturnNpcName(npc.index, true)); - maxhealth= (heck/5); //mid squishy + float pos[3], ang[3]; + GetEntPropVector(npc.index, Prop_Data, "m_vecAbsOrigin", pos); + GetEntPropVector(npc.index, Prop_Data, "m_angRotation", ang); + + int bossMaxHealth = ReturnEntityMaxHealth(npc.index); + + if(i_RaidGrantExtra[npc.index] >= 4) + { + CPrintToChatAll("{crimson} 저것이 끔찍한 감염체들을 소환했다."); - spawn_index = NPC_CreateByName("npc_random_zombie", npc.index, pos, ang, GetTeam(npc.index)); - NpcAddedToZombiesLeftCurrently(spawn_index, true); - if(spawn_index > MaxClients) - { - NpcStats_CopyStats(npc.index, spawn_index); - b_thisNpcIsABoss[spawn_index] = true; - SetEntProp(spawn_index, Prop_Data, "m_iHealth", maxhealth); - SetEntProp(spawn_index, Prop_Data, "m_iMaxHealth", maxhealth); - } - maxhealth= (heck/5); //the tankiest - spawn_index = NPC_CreateByName("npc_random_zombie", npc.index, pos, ang, GetTeam(npc.index)); - NpcAddedToZombiesLeftCurrently(spawn_index, true); - if(spawn_index > MaxClients) - { - NpcStats_CopyStats(npc.index, spawn_index); - b_thisNpcIsABoss[spawn_index] = true; - SetEntProp(spawn_index, Prop_Data, "m_iHealth", maxhealth); - SetEntProp(spawn_index, Prop_Data, "m_iMaxHealth", maxhealth); - } - maxhealth= (heck/10); //the tankiest - spawn_index = NPC_CreateByName("npc_random_zombie", npc.index, pos, ang, GetTeam(npc.index)); - NpcAddedToZombiesLeftCurrently(spawn_index, true); - if(spawn_index > MaxClients) - { - NpcStats_CopyStats(npc.index, spawn_index); - b_thisNpcIsABoss[spawn_index] = true; - SetEntProp(spawn_index, Prop_Data, "m_iHealth", maxhealth); - SetEntProp(spawn_index, Prop_Data, "m_iMaxHealth", maxhealth); - } - } + // 소환할 좀비들의 체력 비율 (20%, 20%, 10%) + float ratios[] = {0.2, 0.2, 0.1}; + + for(int i = 0; i < 3; i++) + { + int spawn_index = NPC_CreateByName("npc_random_poyo", npc.index, pos, ang, GetTeam(npc.index)); + + if(spawn_index > MaxClients) + { + // 체력 계산 및 20만 제한(Clamp) + int finalHealth = RoundToFloor(bossMaxHealth * ratios[i]); + if(finalHealth > 200000) finalHealth = 200000; + + NpcAddedToZombiesLeftCurrently(spawn_index, true); + NpcStats_CopyStats(npc.index, spawn_index); + b_thisNpcIsABoss[spawn_index] = true; + + SetEntProp(spawn_index, Prop_Data, "m_iHealth", finalHealth); + SetEntProp(spawn_index, Prop_Data, "m_iMaxHealth", finalHealth); + } + } + } } float ZsUnspeakable_Absorber(int entity, int victim, float damage, int weapon) @@ -911,7 +902,7 @@ float ZsUnspeakable_Absorber(int entity, int victim, float damage, int weapon) ApplyStatusEffect(entity, victim, "Heavy Presence", 1.0); float damageDealt = 10.0 * RaidModeScaling; - Elemental_AddPheromoneDamage(victim, entity, RoundToNearest(damageDealt), true, true); + Elemental_AddPheromoneDamage(victim, entity, RoundToNearest(damageDealt * 0.5), true, true); return 0.0; } bool ZsUnspeakable_TeleToAnyAffectedOnVoid(ZsUnspeakable npc) @@ -1253,7 +1244,7 @@ void ZsUnspeakableSelfDefense(ZsUnspeakable npc, float gameTime, int target, flo float vecHit[3]; WorldSpaceCenter(target, vecHit); - float damageDealt = 8.0 * RaidModeScaling; + float damageDealt = 10.0 * RaidModeScaling; SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_CLUB, -1, _, vecHit); Elemental_AddPheromoneDamage(target, npc.index, RoundToNearest(damageDealt * 0.15), true, true); @@ -1440,6 +1431,10 @@ public void ZsUnspeakableWin(int entity) { CPrintToChatAll("{crimson}불결한 존재{default}: 계획대로 착착 진행되면 참 기분 좋지"); } + case 5: + { + CPrintToChatAll("{crimson}불결한 존재{default}: 그 누구도 우리의 권위에 도전할 순 없다. 우리의 힘은 끝이 없다."); + } } } diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_heavy.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_heavy.sp index 8cdcc5451b..8158b4975f 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_heavy.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_heavy.sp @@ -142,6 +142,11 @@ methodmap Allyheavy < CClotBody npc.m_iWearable3 = npc.EquipItem("head", "models/player/items/heavy/xms_heavy_sandvichsafe.mdl"); AcceptEntityInput(npc.m_iWearable3, "SetModelScale"); + npc.m_iTeamGlow = TF2_CreateGlow(npc.index); + npc.m_bTeamGlowDefault = false; + SetVariantColor(view_as({255, 255, 255, 255})); + AcceptEntityInput(npc.m_iTeamGlow, "SetGlowColor"); + SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", 0); if(npc.m_bScalesWithWaves) diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_medic.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_medic.sp index 34b379ac02..2d42c60082 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_medic.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_medic.sp @@ -117,6 +117,10 @@ methodmap Allymedic < CClotBody npc.m_bnew_target = false; npc.StartPathing(); + npc.m_iTeamGlow = TF2_CreateGlow(npc.index); + npc.m_bTeamGlowDefault = false; + SetVariantColor(view_as({255, 255, 255, 255})); + AcceptEntityInput(npc.m_iTeamGlow, "SetGlowColor"); int skin = 0; SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); @@ -313,7 +317,7 @@ static int Medic_Work(Allymedic npc, float distance) if(npc.m_iTargetWalkTo) { if (GetTeam(npc.m_iTargetWalkTo)==GetTeam(npc.index) && - b_BobsCuringHand_Revived[npc.m_iTargetWalkTo] >= 40 && + b_BobsCuringHand_Revived[npc.m_iTargetWalkTo] >= 0 && TeutonType[npc.m_iTargetWalkTo] == TEUTON_NONE && dieingstate[npc.m_iTargetWalkTo] > 0 && !b_LeftForDead[npc.m_iTargetWalkTo]) diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_sniper.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_sniper.sp index da3b744c65..fe54a0fc29 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_sniper.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_sniper.sp @@ -119,6 +119,11 @@ methodmap AllySniper < CClotBody b_NpcIsInvulnerable[npc.index] = true; npc.m_bScalesWithWaves = false; + npc.m_iTeamGlow = TF2_CreateGlow(npc.index); + npc.m_bTeamGlowDefault = false; + SetVariantColor(view_as({255, 255, 255, 255})); + AcceptEntityInput(npc.m_iTeamGlow, "SetGlowColor"); + if(npc.m_bScalesWithWaves) { SetEntityRenderMode(npc.index, RENDER_TRANSCOLOR); @@ -403,8 +408,8 @@ int AllySniperSelfDefense(AllySniper npc, float gameTime) if(gameTime > npc.m_flNextMeleeAttack) { - npc.m_flAttackHappens = gameTime + 0.0; - npc.m_flDoingAnimation = gameTime + 0.95; + npc.m_flAttackHappens = gameTime + 0.2; + npc.m_flDoingAnimation = gameTime + 0.2; npc.m_flNextMeleeAttack = gameTime + 1.75; } return 1; diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_soldier.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_soldier.sp index 540c1bf3b2..9b0308f20c 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_soldier.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/npc_zs_ally_soldier.sp @@ -129,6 +129,11 @@ methodmap Allysoldier < CClotBody npc.m_flGetClosestTargetTime = 0.0; npc.StartPathing(); + npc.m_iTeamGlow = TF2_CreateGlow(npc.index); + npc.m_bTeamGlowDefault = false; + SetVariantColor(view_as({255, 255, 255, 255})); + AcceptEntityInput(npc.m_iTeamGlow, "SetGlowColor"); + int skin = 0; SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); @@ -160,120 +165,128 @@ methodmap Allysoldier < CClotBody static void Allysoldier_ClotThink(int iNPC) { - Allysoldier npc = view_as(iNPC); - float gametime = GetGameTime(npc.index); - if(npc.m_flNextDelayTime > gametime) - return; - npc.m_flNextDelayTime = gametime + DEFAULT_UPDATE_DELAY_FLOAT; - - //float Range = ALLYSOLDIER_RANGE; - //spawnRing_Vectors(VecSelfNpcabs, Range * 2.0, 0.0, 0.0, 0.0, "materials/sprites/laserbeam.vmt", 255, 200, 80, 150, 1, 0.1, 3.0, 0.1, 3); - //spawnRing_Vectors(VecSelfNpcabs, Range * 2.0, 0.0, 0.0, 25.0, "materials/sprites/laserbeam.vmt", 255, 50, 50, 200, 1, /*duration*/ 0.11, 3.0, 5.0, 1); - - npc.Update(); - if(npc.m_blPlayHurtAnimation) - { - npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); - npc.m_blPlayHurtAnimation = false; - npc.PlayHurtSound(); - } + Allysoldier npc = view_as(iNPC); + float gametime = GetGameTime(npc.index); + + if(npc.m_flNextDelayTime > gametime) + return; + npc.m_flNextDelayTime = gametime + DEFAULT_UPDATE_DELAY_FLOAT; + + npc.Update(); if(npc.m_flNextThinkTime > gametime) - return; - npc.m_flNextThinkTime = gametime + 0.1; - - float VecSelfNpcabs[3]; GetEntPropVector(npc.index, Prop_Data, "m_vecAbsOrigin", VecSelfNpcabs); - Allysoldier_ApplyBuffInLocation_Optimized(VecSelfNpcabs, GetTeam(npc.index), npc.index); - - int ally = npc.m_iTargetWalkTo; - - if(i_Target[npc.index] == -1 || npc.m_flGetClosestTargetTime < gametime) - { - npc.m_iTarget = GetClosestTarget(npc.index, _, _, _, _, _, _, _, 99999.9); - npc.m_flGetClosestTargetTime = gametime + 1.0; + return; + npc.m_flNextThinkTime = gametime + 0.1; + + float VecSelfNpcabs[3]; + GetEntPropVector(npc.index, Prop_Data, "m_vecAbsOrigin", VecSelfNpcabs); + Allysoldier_ApplyBuffInLocation_Optimized(VecSelfNpcabs, GetTeam(npc.index), npc.index); + + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + int ally = npc.m_iTargetWalkTo; + + if(i_Target[npc.index] == -1 || npc.m_flGetClosestTargetTime < gametime) + { + npc.m_iTarget = GetClosestTarget(npc.index, _, _, _, _, _, _, _, 99999.9); + npc.m_flGetClosestTargetTime = gametime + 1.0; - ally = GetClosestAllyPlayer(npc.index); - npc.m_iTargetWalkTo = ally; - } - - 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(Allysoldier_Work(npc,gametime,npc.m_iTarget,flDistanceToTarget,vecTarget)) - { - case 0: - { - if(npc.m_iChanged_WalkCycle != 0) - { - npc.m_bisWalking = true; - npc.m_bAllowBackWalking = false; - npc.m_iChanged_WalkCycle = 0; - npc.SetActivity("ACT_MP_RUN_PRIMARY"); - npc.m_flSpeed = 240.0; - npc.StartPathing(); - } - if(flDistanceToTarget < npc.GetLeadRadius()) - { - float vPredictedPos[3]; - PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); - npc.SetGoalVector(vPredictedPos); - } - else - { - npc.SetGoalEntity(npc.m_iTarget); - } - } - case 1: - { - if(npc.m_iChanged_WalkCycle != 1) - { - npc.m_bisWalking = false; - npc.m_bAllowBackWalking = false; - npc.m_iChanged_WalkCycle = 1; - npc.SetActivity("ACT_MP_STAND_PRIMARY"); - npc.m_flSpeed = 0.0; - npc.StopPathing(); - } - } - case 2: - { - if(npc.m_iChanged_WalkCycle != 2) - { - npc.m_bisWalking = true; - npc.m_bAllowBackWalking = true; - npc.m_iChanged_WalkCycle = 2; - npc.SetActivity("ACT_MP_RUN_PRIMARY"); - npc.m_flSpeed = 240.0; - npc.StartPathing(); - } - float vBackoffPos[3]; - BackoffFromOwnPositionAndAwayFromEnemy(npc, npc.m_iTarget,_,vBackoffPos); - npc.SetGoalVector(vBackoffPos, true); - } - } - } - else - { - if(ally > 0) - { - float vecTarget[3]; WorldSpaceCenter(ally, vecTarget); - float vecSelf[3]; WorldSpaceCenter(npc.index, vecSelf); - float flDistanceToTarget = GetVectorDistance(vecTarget, vecSelf, true); + ally = GetClosestAllyPlayer(npc.index); + npc.m_iTargetWalkTo = ally; + } + + 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 > 25000.0) - { - npc.SetGoalEntity(ally); - npc.StartPathing(); - return; - } - } + switch(Allysoldier_Work(npc, gametime, npc.m_iTarget, flDistanceToTarget, vecTarget)) + { + case 0: // 추격 상태 + { + if(npc.m_iChanged_WalkCycle != 0) + { + npc.m_bisWalking = true; + npc.m_bAllowBackWalking = false; + npc.m_iChanged_WalkCycle = 0; + npc.SetActivity("ACT_MP_RUN_PRIMARY"); + npc.m_flSpeed = 240.0; + npc.StartPathing(); + } + + if(flDistanceToTarget < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTarget, _, _, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + npc.StartPathing(); + } + } + case 1: // 정지/사격 상태 + { + if(npc.m_iChanged_WalkCycle != 1) + { + npc.m_bisWalking = false; + npc.m_iChanged_WalkCycle = 1; + npc.SetActivity("ACT_MP_STAND_PRIMARY"); + npc.m_flSpeed = 0.0; + npc.StopPathing(); + } + } + case 2: // 후퇴 상태 + { + if(npc.m_iChanged_WalkCycle != 2) + { + npc.m_bisWalking = true; + npc.m_bAllowBackWalking = true; + npc.m_iChanged_WalkCycle = 2; + npc.SetActivity("ACT_MP_RUN_PRIMARY"); + npc.m_flSpeed = 240.0; + npc.StartPathing(); + } + float vBackoffPos[3]; + BackoffFromOwnPositionAndAwayFromEnemy(npc, npc.m_iTarget, _, vBackoffPos); + npc.SetGoalVector(vBackoffPos, true); + } + } + } + else // 적이 없을 때 (아군 추적) + { + if(ally > 0) + { + float vecTarget[3]; WorldSpaceCenter(ally, vecTarget); + float vecSelf[3]; WorldSpaceCenter(npc.index, vecSelf); + float flDistanceToTarget = GetVectorDistance(vecTarget, vecSelf, true); - npc.StopPathing(); - npc.m_flGetClosestTargetTime = 0.0; - } - npc.PlayIdleAlertSound(); + // 아군과 200 유닛 이상 떨어지면 추적 실행 (제곱값 40000.0) + if(flDistanceToTarget > 40000.0) + { + npc.m_iChanged_WalkCycle = 0; + npc.m_flSpeed = 240.0; + npc.SetActivity("ACT_MP_RUN_PRIMARY"); + npc.FaceTowards(vecTarget, 20000.0); + npc.SetGoalEntity(ally); + npc.StartPathing(); + return; // 중요: 이동 명령을 내렸으므로 아래의 StopPathing을 건너뜀 + } + } + + // 목적지에 도착했거나 대상이 없으면 정지 + npc.StopPathing(); + npc.m_iChanged_WalkCycle = -1; // 상태 초기화 + npc.m_flGetClosestTargetTime = 0.0; + } + npc.PlayIdleAlertSound(); } static int Allysoldier_Work(Allysoldier npc, float gameTime, int target, float distance, float vecTarget[3]) diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_random_poyo.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_random_poyo.sp new file mode 100644 index 0000000000..38539093a6 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_random_poyo.sp @@ -0,0 +1,160 @@ +#pragma semicolon 1 +#pragma newdecls required + + +void PoyoSummonRandom_OnMapStart_NPC() +{ + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Random Boss"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_random_poyo"); + strcopy(data.Icon, sizeof(data.Icon), "void_gate"); + data.IconCustom = true; + data.Flags = MVM_CLASS_FLAG_MINIBOSS; + data.Category = Type_Hidden; + data.Func = ClotSummon; + data.Precache = ClotPrecache; + NPC_Add(data); + +} + +static void ClotPrecache() +{ + //precaches said npcs. + NPC_GetByPlugin("npc_zs_poisonzombie_fortified_giant"); + NPC_GetByPlugin("npc_zs_the_shit_slapper"); + NPC_GetByPlugin("npc_zs_bastardzine"); + NPC_GetByPlugin("npc_zs_butcher"); + NPC_GetByPlugin("npc_zs_amplification"); + NPC_GetByPlugin("npc_zs_howler"); + NPC_GetByPlugin("npc_zs_zombine"); + NPC_GetByPlugin("npc_zs_bonemesh"); +} + +bool SamePoyoDisallow[9]; +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team, const char[] data) +{ + return PoyoSummonRandom(vecPos, vecAng, team, data); +} +methodmap PoyoSummonRandom < CClotBody +{ + public PoyoSummonRandom(float vecPos[3], float vecAng[3], int ally, const char[] data) + { + PoyoSummonRandom npc = view_as(CClotBody(vecPos, vecAng, "models/empty.mdl", "0.8", "700", ally)); + + i_NpcWeight[npc.index] = 1; + + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = 0; + npc.m_iStepNoiseType = 0; + npc.m_iNpcStepVariation = 0; + npc.m_bDissapearOnDeath = true; + + func_NPCDeath[npc.index] = view_as(PoyoSummonRandom_NPCDeath); + func_NPCThink[npc.index] = view_as(PoyoSummonRandom_ClotThink); + + i_RaidGrantExtra[npc.index] = StringToInt(data); + if(i_RaidGrantExtra[npc.index] <= 40) + { + Zero(SamePoyoDisallow); + //Reset + } + + if(TeleportDiversioToRandLocation(npc.index,true,1500.0, 700.0) == 2) + { + TeleportDiversioToRandLocation(npc.index, true); + } + + return npc; + } +} + +public void PoyoSummonRandom_ClotThink(int iNPC) +{ + SmiteNpcToDeath(iNPC); +} + +public void PoyoSummonRandom_NPCDeath(int entity) +{ + PoyoSummonRandom npc = view_as(entity); + float VecSelfNpcabs[3]; GetEntPropVector(npc.index, Prop_Data, "m_vecAbsOrigin", VecSelfNpcabs); + //Spawns a random raid. + PoyoSummonRaidboss(entity); +} + + +void PoyoSummonRaidboss(int ZombieSummonbase) +{ + Enemy enemy; + enemy.Health = ReturnEntityMaxHealth(ZombieSummonbase); + enemy.Is_Boss = view_as(b_thisNpcIsABoss[ZombieSummonbase]); + enemy.Is_Immune_To_Nuke = true; + enemy.ExtraMeleeRes = fl_Extra_MeleeArmor[ZombieSummonbase]; + enemy.ExtraRangedRes = fl_Extra_RangedArmor[ZombieSummonbase]; + enemy.ExtraSpeed = fl_Extra_Speed[ZombieSummonbase]; + enemy.ExtraDamage = fl_Extra_Damage[ZombieSummonbase]; + enemy.ExtraSize = 1.0; + enemy.Team = GetTeam(ZombieSummonbase); + enemy.Does_Not_Scale = 1; //scaling was already done. + //18 is max bosses? + char PluginName[255]; + char CharData[255]; + + Format(CharData, sizeof(CharData), "sc%i;",i_RaidGrantExtra[ZombieSummonbase]); + int NumberRand; + SamePoyoDisallow[0] = true; + while(SamePoyoDisallow[NumberRand]) + { + NumberRand = GetRandomInt(1,10); + } + SamePoyoDisallow[NumberRand] = true; + switch(NumberRand) + { + case 1: + { + PluginName = "npc_zs_poisonzombie_fortified_giant"; + enemy.Is_Boss = 1; + } + case 2: + { + PluginName = "npc_zs_the_shit_slapper"; + enemy.Is_Boss = 1; + } + case 3: + { + PluginName = "npc_zs_bastardzine"; + enemy.Is_Boss = 1; + } + case 4: + { + PluginName = "npc_zs_butcher"; + enemy.Is_Boss = 1; + } + case 5: + { + PluginName = "npc_zs_amplification"; + enemy.Is_Boss = 1; + } + case 6: + { + PluginName = "npc_zs_howler"; + enemy.Is_Boss = 1; + } + case 7: + { + PluginName = "npc_zs_zombine"; + enemy.Is_Boss = 1; + } + case 8: + { + PluginName = "npc_zs_bonemesh"; + enemy.Is_Boss = 1; + } + } + Format(enemy.Data, sizeof(enemy.Data), "%s",CharData); + enemy.Index = NPC_GetByPlugin(PluginName); + + + Waves_AddNextEnemy(enemy); + Zombies_Currently_Still_Ongoing += 1; +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_random_zombie.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_random_zombie.sp index 9544e0dcce..14d26515a3 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_random_zombie.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_random_zombie.sp @@ -24,15 +24,14 @@ static void ClotPrecache() NPC_GetByPlugin("npc_zs_the_shit_slapper"); NPC_GetByPlugin("npc_zs_bastardzine"); NPC_GetByPlugin("npc_zs_butcher"); - NPC_GetByPlugin("npc_zmain_headcrabzombie"); - NPC_GetByPlugin("npc_zmain_poisonzombie"); NPC_GetByPlugin("npc_zs_amplification"); NPC_GetByPlugin("npc_zs_howler"); - NPC_GetByPlugin("npc_zs_red_marrow"); + NPC_GetByPlugin("npc_zs_zombine"); NPC_GetByPlugin("npc_zs_bonemesh"); + NPC_GetByPlugin("npc_zs_red_marrow"); } -bool SameZombieDisallow[11]; +bool SameZombieDisallow[10]; static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team, const char[] data) { return ZombieSummonRandom(vecPos, vecAng, team, data); @@ -134,22 +133,22 @@ void ZombieSummonRaidboss(int ZombieSummonbase) } case 5: { - PluginName = "npc_zmain_headcrabzombie"; + PluginName = "npc_zs_amplification"; enemy.Is_Boss = 1; } case 6: { - PluginName = "npc_zmain_poisonzombie"; + PluginName = "npc_zs_howler"; enemy.Is_Boss = 1; } case 7: { - PluginName = "npc_zs_amplification"; + PluginName = "npc_zs_zombine"; enemy.Is_Boss = 1; } case 8: { - PluginName = "npc_zs_howler"; + PluginName = "npc_zs_bonemesh"; enemy.Is_Boss = 1; } case 9: @@ -157,11 +156,6 @@ void ZombieSummonRaidboss(int ZombieSummonbase) PluginName = "npc_zs_red_marrow"; enemy.Is_Boss = 1; } - case 10: - { - PluginName = "npc_zs_bonemesh"; - enemy.Is_Boss = 1; - } } Format(enemy.Data, sizeof(enemy.Data), "%s",CharData); enemy.Index = NPC_GetByPlugin(PluginName); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_amplification.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_amplification.sp index 610cdfc9b7..23c4af302a 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_amplification.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_amplification.sp @@ -194,7 +194,7 @@ public void Amplification_ClotThink(int iNPC) { KillFeed_SetKillIcon(npc.index, "saw_kill"); spawnRing_Vectors(vecMe, 100.0, 0.0, 0.0, 0.0, "materials/sprites/laserbeam.vmt", 255, 50, 50, 200, 1, 0.4, 6.0, 0.1, 1, 1000.0); - Explode_Logic_Custom(0.0, -1, npc.index, -1, vecMe, 400.0, _, _, true, _, false, _, Amplification_ExplodePost); + Explode_Logic_Custom(5.0, -1, npc.index, -1, vecMe, 400.0, _, _, true, _, false, _, Amplification_ExplodePost); } } @@ -281,6 +281,7 @@ public void Amplification_ExplodePost(int attacker, int victim, float damage, in float vic_vec[3]; WorldSpaceCenter(victim, vic_vec); ParticleEffectAt(vic_vec, "water_bulletsplash01", 1.5); Elemental_AddPheromoneDamage(victim, attacker, view_as(attacker).m_bElite ? 15 : 12); + StartBleedingTimer(victim, attacker, 5.0, 2, -1, DMG_TRUEDAMAGE, 0); // 400 x 0.2 x 0.15 // 500 x 0.2 x 0.15 } diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_bastardzine.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_bastardzine.sp index e75ed519e6..0398e805e5 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_bastardzine.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_bastardzine.sp @@ -195,6 +195,11 @@ methodmap Bastardzine < CClotBody func_NPCThink[npc.index] = Bastardzine_BastardzineThink; func_NPCOnTakeDamage[npc.index] = Generic_OnTakeDamage; + float wave = float(Waves_GetRoundScale()+1); //Wave scaling + + wave *= 0.133333; + + npc.m_flWaveScale = wave; //IDLE npc.m_flSpeed = 350.0; @@ -330,9 +335,9 @@ public void Bastardzine_BastardzineThink(int iNPC) { { if(!ShouldNpcDealBonusDamage(target)) - SDKHooks_TakeDamage(target, npc.index, npc.index, 200.0, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, 75.0 * npc.m_flWaveScale, DMG_CLUB, -1, _, vecHit); else - SDKHooks_TakeDamage(target, npc.index, npc.index, 120.0, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, 100.0 * npc.m_flWaveScale, DMG_CLUB, -1, _, vecHit); } npc.PlayMeleeHitSound(); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_butcher.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_butcher.sp index 631af3440c..8c49a5b943 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_butcher.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_butcher.sp @@ -119,6 +119,12 @@ methodmap Butcher < CClotBody npc.m_flGetClosestTargetTime = 0.0; npc.StartPathing(); npc.m_flSpeed = 300.0; + + float wave = float(Waves_GetRoundScale()+1); //Wave scaling + + wave *= 0.133333; + + npc.m_flWaveScale = wave; int skin = 1; SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); @@ -286,11 +292,11 @@ void ButcherSelfDefense(Butcher npc, float gameTime, int target, float distance) if(IsValidEnemy(npc.index, target)) { - float damageDealt = 20.0; + float damageDealt = 50.0; if(!ShouldNpcDealBonusDamage(target)) - damageDealt *= 1.5; + damageDealt *= 0.5; - SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt * npc.m_flWaveScale, DMG_CLUB, -1, _, vecHit); // Hit sound npc.PlayMeleeHitSound(); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_flesh_creeper.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_flesh_creeper.sp index 6ef16a918b..aa2b938ec4 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_flesh_creeper.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_flesh_creeper.sp @@ -173,7 +173,6 @@ methodmap FleshCreeper < CClotBody npc.m_iStepNoiseType = STEPSOUND_NORMAL; npc.m_iNpcStepVariation = STEPSOUND_NORMAL; - i_ClosestAllyCD[npc.index] = 0.0; npc.m_iState = 0; diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_malfunctioning_heavy.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_malfunctioning_heavy.sp index 9cab521890..194c63ec5c 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_malfunctioning_heavy.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_malfunctioning_heavy.sp @@ -24,7 +24,7 @@ static char g_IdleSounds[][] = { }; static char g_IntroSound[][] = { - "npc/strider/striderx_alert2.wav", + "vo/heavy_domination12.mp3", }; static char g_MeleeHitSounds[][] = { @@ -43,7 +43,7 @@ static char g_Overheat[][] = { "npc/strider/fire.wav", }; -static float fl_DefaultSpeed_Witch = 200.0; +static float fl_DefaultSpeed_Witch = 270.0; public void ZsMalfuncHeavy_OnMapStart_NPC() { @@ -134,15 +134,6 @@ methodmap ZsMalfuncHeavy < CClotBody public void PlayOverHeatSound() { EmitSoundToAll(g_Overheat[GetRandomInt(0, sizeof(g_Overheat) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 90); } - public void ArmorSet(float resistance = -1.0, bool uber = false) - { - if(resistance != -1.0 && resistance >= 0.0) - { - this.m_flMeleeArmor = resistance; - this.m_flRangedArmor = resistance; - } - b_NpcIsInvulnerable[this.index] = uber; - } public ZsMalfuncHeavy(float vecPos[3], float vecAng[3], int ally, const char[] data) { @@ -169,6 +160,14 @@ methodmap ZsMalfuncHeavy < CClotBody SetVariantInt(1); AcceptEntityInput(npc.index, "SetBodyGroup"); + + if(!IsValidEntity(RaidBossActive)) + { + RaidBossActive = EntIndexToEntRef(npc.index); + RaidModeTime = GetGameTime(npc.index) + 9000.0; + RaidModeScaling = 0.0; + RaidAllowsBuildings = true; + } int skin = 5; SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); @@ -180,10 +179,16 @@ methodmap ZsMalfuncHeavy < CClotBody npc.m_iWearable6 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_fists_of_steel/c_fists_of_steel.mdl", "", 1); SetVariantString("1.0"); AcceptEntityInput(npc.m_iWearable6, "SetModelScale"); + npc.m_iWearable7 = npc.EquipItemSeperate("models/buildables/sentry_shield.mdl",_,_,_,-100.0,true); + SetVariantString("2.5"); + AcceptEntityInput(npc.m_iWearable7, "SetModelScale"); + SetEntProp(npc.m_iWearable7, Prop_Send, "m_nSkin", 1); + if(IsValidEntity(npc.m_iWearable7)) + SetParent(npc.index, npc.m_iWearable7); func_NPCDeath[npc.index] = ZsMalfuncHeavy_NPCDeath; func_NPCThink[npc.index] = ZsMalfuncHeavy_ClotThink; - func_NPCOnTakeDamage[npc.index] = Generic_OnTakeDamage; + func_NPCOnTakeDamage[npc.index] = ZsMalfuncHeavy_OnTakeDamage; npc.m_flSpeed = fl_DefaultSpeed_Witch; npc.Anger = false; npc.b_Enraged = false; @@ -237,7 +242,6 @@ public void ZsMalfuncHeavy_ClotThink(int iNPC) CPrintToChatAll("{green}오버히터{default}: {crimson}널 박살내주마."); npc.PlayIdleSound(); npc.Anger = true; - npc.ArmorSet(npc.m_fbGunout ? 1.08 : 1.25); npc.i_Hit = 0; npc.f_Overheat_Cooldown = gameTime + 10.0; npc.m_flSpeed = npc.m_fbGunout ? fl_DefaultSpeed_Witch * 0.9: fl_DefaultSpeed_Witch * 0.8; @@ -376,17 +380,27 @@ static void ZsMalfuncHeavy_SelfDefense(ZsMalfuncHeavy npc, float gameTime, int t } } } -/* + static Action ZsMalfuncHeavy_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) { //Valid attackers only. - if(attacker < 1) + if(attacker <= 0) return Plugin_Continue; - ZsMalfuncHeavy npc = view_as(victim); + //ZsMalfuncHeavy npc = view_as(victim); + + float vecTarget[3]; WorldSpaceCenter(attacker, vecTarget ); + float VecSelfNpc[3]; WorldSpaceCenter(victim, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + + if(flDistanceToTarget < (300.0 * 300.0)) + { + damage = 0.0; + return Plugin_Handled; + } return Plugin_Continue; -}*/ +} static void ZsMalfuncHeavy_NPCDeath(int entity) { @@ -409,6 +423,9 @@ static void ZsMalfuncHeavy_NPCDeath(int entity) if(IsValidEntity(npc.m_iWearable6)) RemoveEntity(npc.m_iWearable6); + + if(IsValidEntity(npc.m_iWearable7)) + RemoveEntity(npc.m_iWearable7); npc.PlayDeathSound(); } \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_nest.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_nest.sp index db91c5d91f..e08f5f6574 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_nest.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_nest.sp @@ -227,9 +227,10 @@ static char g_10wave[][] = { "npc_zs_shadow_walker", "npc_zs_skeleton", "npc_zs_gore_blaster", - "npc_fastzombie_fortified", - "npc_headcrabzombie_fortified", "npc_torsoless_headcrabzombie", + "npc_fastzombie", + "npc_headcrabzombie", + "npc_zs_headcrab", }; static char g_20wave[][] = { @@ -240,6 +241,9 @@ static char g_20wave[][] = { "npc_zs_gore_blaster", "npc_zs_runner", "npc_zs_spitter", + "npc_fastzombie_fortified", + "npc_headcrabzombie_fortified", + "npc_zs_fast_headcrab", }; static char g_30wave[][] = { @@ -254,15 +258,19 @@ static char g_30wave[][] = { "npc_zs_zombie_soldier", "npc_zs_zombie_soldier_pickaxe", "npc_zs_zombie_spy", - "npc_zombie_pyro_giant_main", + "npc_infected_tomislav_main", + "npc_zs_hmo", "npc_zombie_scout_grave", "npc_zombie_soldier_grave", "npc_zombie_spy_grave", "npc_zombie_demo_main", "npc_zombie_heavy_grave", + "npc_zombie_heavy_giant_grave", + "npc_sniper_main", }; static char g_40wave[][] = { "npc_zs_kamikaze_demo", + "npc_zs_manhattan_parrot", "npc_zs_medic_healer", "npc_zs_huntsman", "npc_zs_zombie_demoknight", @@ -276,7 +284,6 @@ static char g_40wave[][] = { "npc_zs_cleaner", "npc_zs_eradicator", "npc_zs_firefighter", - "npc_zombine", "npc_zs_medic_main", "npc_zs_mlsm", "npc_zs_sam", @@ -284,6 +291,7 @@ static char g_40wave[][] = { "npc_zs_zombie_breadmonster", "npc_zs_zombie_fatscout", "npc_zs_zombie_fatspy", + "npc_zombie_pyro_giant_main", }; public void Nest_ClotThink(int iNPC) @@ -350,28 +358,30 @@ public void Nest_ClotThink(int iNPC) if(GetTeam(iNPC) == TFTeam_Red) { - IncreaseSpawnRates *= 0.5; //way slower. + IncreaseSpawnRates *= 0.5; } if(i_currentwave[iNPC] < 15) { int idx = GetRandomInt(0, sizeof(g_10wave) - 1); strcopy(EnemyToSpawn, sizeof(EnemyToSpawn), g_10wave[idx]); - //IncreaseSpawnRates *= 0.8; + IncreaseSpawnRates *= 0.5; } else if(i_currentwave[iNPC] < 28) { int idx = GetRandomInt(0, sizeof(g_20wave) - 1); strcopy(EnemyToSpawn, sizeof(EnemyToSpawn), g_20wave[idx]); - //IncreaseSpawnRates *= 0.8; + IncreaseSpawnRates *= 0.5; } else if(i_currentwave[iNPC] < 41) { int idx = GetRandomInt(0, sizeof(g_30wave) - 1); strcopy(EnemyToSpawn, sizeof(EnemyToSpawn), g_30wave[idx]); + IncreaseSpawnRates *= 0.5; } else { int idx = GetRandomInt(0, sizeof(g_40wave) - 1); strcopy(EnemyToSpawn, sizeof(EnemyToSpawn), g_40wave[idx]); + IncreaseSpawnRates *= 0.5; } if(Rogue_Mode()) diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_poisonzombie_fortified_giant.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_poisonzombie_fortified_giant.sp index 401ff2570c..5073a91d3b 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_poisonzombie_fortified_giant.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_poisonzombie_fortified_giant.sp @@ -124,7 +124,7 @@ methodmap ZSFortifiedGiantPoisonZombie < CClotBody public ZSFortifiedGiantPoisonZombie(float vecPos[3], float vecAng[3], int ally) { - ZSFortifiedGiantPoisonZombie npc = view_as(CClotBody(vecPos, vecAng, "models/zombie/poison.mdl", "1.75", "15000", ally, false, true)); + ZSFortifiedGiantPoisonZombie npc = view_as(CClotBody(vecPos, vecAng, "models/zombie/poison.mdl", "2.2", "15000", ally, false, true)); i_NpcWeight[npc.index] = 4; @@ -140,7 +140,6 @@ methodmap ZSFortifiedGiantPoisonZombie < CClotBody npc.m_iStepNoiseType = STEPSOUND_NORMAL; npc.m_iNpcStepVariation = STEPTYPE_NORMAL; - //IDLE npc.m_flAttackHappenswillhappen = false; npc.m_flSpeed = 231.0; @@ -148,8 +147,6 @@ methodmap ZSFortifiedGiantPoisonZombie < CClotBody return npc; } - - } @@ -325,9 +322,58 @@ public Action ZSFortifiedGiantPoisonZombie_OnTakeDamage(int victim, int &attacke npc.m_blPlayHurtAnimation = true; } + if(!NpcStats_IsEnemySilenced(victim)) + { + if(!npc.bXenoInfectedSpecialHurt) + { + npc.bXenoInfectedSpecialHurt = true; + npc.flXenoInfectedSpecialHurtTime = GetGameTime(npc.index) + 2.0; + SetEntityRenderMode(npc.index, RENDER_TRANSCOLOR); + SetEntityRenderColor(npc.index, 150, 255, 150, 65); + CreateTimer(2.0, ZSFortifiedGiantPoisonZombie_Revert_Poison_Zombie_Resistance, EntIndexToEntRef(victim), TIMER_FLAG_NO_MAPCHANGE); + CreateTimer(10.0, ZSFortifiedGiantPoisonZombie_Revert_Poison_Zombie_Resistance_Enable, EntIndexToEntRef(victim), TIMER_FLAG_NO_MAPCHANGE); + } + float TrueArmor = 1.0; + if(!NpcStats_IsEnemySilenced(victim)) + { + if(fl_TotalArmor[npc.index] == 1.0) + { + if(npc.flXenoInfectedSpecialHurtTime > GetGameTime(npc.index)) + { + TrueArmor *= 0.25; + fl_TotalArmor[npc.index] = TrueArmor; + OnTakeDamageNpcBaseArmorLogic(victim, attacker, damage, damagetype, true); + } + } + } + fl_TotalArmor[npc.index] = TrueArmor; + } + return Plugin_Changed; } +public Action ZSFortifiedGiantPoisonZombie_Revert_Poison_Zombie_Resistance(Handle timer, int ref) +{ + int zombie = EntRefToEntIndex(ref); + if(IsValidEntity(zombie)) + { + SetEntityRenderMode(zombie, RENDER_NORMAL); + SetEntityRenderColor(zombie, 255, 255, 255, 255); + } + return Plugin_Handled; +} + +public Action ZSFortifiedGiantPoisonZombie_Revert_Poison_Zombie_Resistance_Enable(Handle timer, int ref) +{ + int zombie = EntRefToEntIndex(ref); + if(IsValidEntity(zombie)) + { + ZSFortifiedGiantPoisonZombie npc = view_as(zombie); + npc.bXenoInfectedSpecialHurt = false; + } + return Plugin_Handled; +} + public void ZSFortifiedGiantPoisonZombie_NPCDeath(int entity) { ZSFortifiedGiantPoisonZombie npc = view_as(entity); diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_red_marrow.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_red_marrow.sp index 0554a293d5..c299618af4 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_red_marrow.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_red_marrow.sp @@ -102,7 +102,7 @@ methodmap RedMarrow < CClotBody FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); - int iActivity = npc.LookupActivity("ACT_HL2MP_WALK_ZOMBIE_01"); + int iActivity = npc.LookupActivity("ACT_HL2MP_RUN_ZOMBIE"); if(iActivity > 0) npc.StartActivity(iActivity); if(npc.index > 0 && npc.index < 2048) { @@ -120,11 +120,20 @@ methodmap RedMarrow < CClotBody func_NPCThink[npc.index] = RedMarrow_ClotThink; func_NPCOnTakeDamage[npc.index] = RedMarrow_OnTakeDamage; + AddNpcToAliveList(npc.index, 1); + + float wave = float(Waves_GetRoundScale()+1); //Wave scaling + + wave *= 0.133333; + + npc.m_flWaveScale = wave; + SetEntityRenderMode(npc.index, RENDER_TRANSCOLOR); SetEntityRenderColor(npc.index, 255, 0, 0, 255); npc.m_flMeleeArmor = 0.77; npc.m_flRangedArmor = 0.7; + npc.Anger = false; npc.StartPathing(); @@ -219,9 +228,9 @@ public void RedMarrow_ClotThink(int iNPC) { { if(!ShouldNpcDealBonusDamage(target)) - SDKHooks_TakeDamage(target, npc.index, npc.index, 80.0, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, 80.0 * npc.m_flWaveScale, DMG_CLUB, -1, _, vecHit); else - SDKHooks_TakeDamage(target, npc.index, npc.index, 120.0, DMG_CLUB, -1, _, vecHit); + SDKHooks_TakeDamage(target, npc.index, npc.index, 120.0 * npc.m_flWaveScale, DMG_CLUB, -1, _, vecHit); } npc.PlayMeleeHitSound(); @@ -270,7 +279,7 @@ public Action RedMarrow_OnTakeDamage(int victim, int &attacker, int &inflictor, RedMarrow npc = view_as(victim); - while(g_flRedMarrowAccumulatedDamage[victim] >= threshold) + while(!npc.Anger && g_flRedMarrowAccumulatedDamage[victim] >= threshold) { g_flRedMarrowAccumulatedDamage[victim] -= threshold; @@ -285,7 +294,10 @@ public Action RedMarrow_OnTakeDamage(int victim, int &attacker, int &inflictor, CreateTimer(5.0, RedMarrow_Revert_Resistance_Enable, EntIndexToEntRef(victim), TIMER_FLAG_NO_MAPCHANGE); } } - + if((ReturnEntityMaxHealth(npc.index) * 0.05) >= GetEntProp(npc.index, Prop_Data, "m_iHealth") && !npc.Anger) + { + npc.Anger = true; + } // 헤드샷 쿨다운 로직 (기존 유지) if (npc.m_flHeadshotCooldown < GetGameTime()) { diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_soldier_giant_grave.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_soldier_giant_grave.sp new file mode 100644 index 0000000000..e22350505d --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_soldier_giant_grave.sp @@ -0,0 +1,429 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + "vo/soldier_paincrticialdeath01.mp3", + "vo/soldier_paincrticialdeath02.mp3", + "vo/soldier_paincrticialdeath03.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_IdleSounds[][] = { + "vo/taunts/soldier_taunts01.mp3", + "vo/taunts/soldier_taunts09.mp3", + "vo/taunts/soldier_taunts14.mp3", + +}; + +static const char g_IdleAlertedSounds[][] = { + "vo/taunts/soldier_taunts19.mp3", + "vo/taunts/soldier_taunts20.mp3", + "vo/taunts/soldier_taunts21.mp3", + "vo/taunts/soldier_taunts18.mp3", +}; + +static const char g_MeleeHitSounds[][] = { + "weapons/boxing_gloves_hit1.wav", + "weapons/boxing_gloves_hit2.wav", + "weapons/boxing_gloves_hit3.wav", + "weapons/boxing_gloves_hit4.wav", +}; +static const char g_MeleeAttackSounds[][] = { + "weapons/boxing_gloves_swing1.wav", + "weapons/boxing_gloves_swing2.wav", + "weapons/boxing_gloves_swing4.wav", +}; + +static const char g_RangedAttackSounds[][] = { + "weapons/rocket_shoot.wav", +}; + +static const char g_MeleeMissSounds[][] = { + "weapons/bat_draw_swoosh1.wav", + "weapons/bat_draw_swoosh2.wav", +}; + +void ZSSoldierGiant_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_IdleSounds)); i++) { PrecacheSound(g_IdleSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSound(g_IdleAlertedSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeHitSounds)); i++) { PrecacheSound(g_MeleeHitSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeAttackSounds)); i++) { PrecacheSound(g_MeleeAttackSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeMissSounds)); i++) { PrecacheSound(g_MeleeMissSounds[i]); } + for (int i = 0; i < (sizeof(g_RangedAttackSounds)); i++) { PrecacheSound(g_RangedAttackSounds[i]); } + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Soldier Giant Summoner"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_zs_soldier_giant_grave"); + strcopy(data.Icon, sizeof(data.Icon), "soldier_libertylauncher"); + data.IconCustom = false; + data.Flags = 0; + data.Category = Type_Common; + data.Func = ClotSummon; + NPC_Add(data); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return ZSSoldierGiant(vecPos, vecAng, team); +} +methodmap ZSSoldierGiant < CClotBody +{ + + public void PlayIdleSound() { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + EmitSoundToAll(g_IdleSounds[GetRandomInt(0, sizeof(g_IdleSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(24.0, 48.0); + + + } + + 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_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + public void PlayRangedSound() { + EmitSoundToAll(g_RangedAttackSounds[GetRandomInt(0, sizeof(g_RangedAttackSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + + public void PlayMeleeHitSound() { + EmitSoundToAll(g_MeleeHitSounds[GetRandomInt(0, sizeof(g_MeleeHitSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + + public void PlayMeleeMissSound() { + EmitSoundToAll(g_MeleeMissSounds[GetRandomInt(0, sizeof(g_MeleeMissSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + + + public ZSSoldierGiant(float vecPos[3], float vecAng[3], int ally) + { + ZSSoldierGiant npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.35", "200000", ally, false, true)); + + i_NpcWeight[npc.index] = 3; + + SetVariantInt(2); + AcceptEntityInput(npc.index, "SetBodyGroup"); + + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_MP_RUN_MELEE_ALLCLASS"); + if(iActivity > 0) npc.StartActivity(iActivity); + + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_GIANT; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + + func_NPCDeath[npc.index] = ZSSoldierGiant_NPCDeath; + func_NPCOnTakeDamage[npc.index] = ZSSoldierGiant_OnTakeDamage; + func_NPCThink[npc.index] = ZSSoldierGiant_ClotThink; + + SDKHook(npc.index, SDKHook_OnTakeDamagePost, ZSSoldierGiant_ClotDamaged_Post); + + //IDLE + npc.m_bThisNpcIsABoss = true; + npc.m_flGetClosestTargetTime = 0.0; + npc.StartPathing(); + + + GiveNpcOutLineLastOrBoss(npc.index, true); + npc.m_flSpeed = 200.0; + npc.g_TimesSummoned = 0; + + int skin = 5; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable1 = npc.EquipItem("head", "models/player/items/soldier/soldier_zombie.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + + npc.m_iWearable2 = npc.EquipItem("head", "models/player/items/soldier/bucket.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable2, "SetModelScale"); + + npc.m_iWearable3 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_picket/c_picket.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable3, "SetModelScale"); + + npc.m_iWearable4 = npc.EquipItem("head", "models/player/items/all_class/mtp_bottle_soldier.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable4, "SetModelScale"); + + SetEntProp(npc.m_iWearable1, Prop_Send, "m_nSkin", 1); + + return npc; + } +} + + +public void ZSSoldierGiant_ClotThink(int iNPC) +{ + ZSSoldierGiant 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(); + } + + int PrimaryThreatIndex = npc.m_iTarget; + + if(IsValidEnemy(npc.index, PrimaryThreatIndex)) + { + float vecTarget[3]; WorldSpaceCenter(PrimaryThreatIndex, vecTarget); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + + //Predict their pos. + if(flDistanceToTarget < npc.GetLeadRadius()) { + + float vPredictedPos[3]; PredictSubjectPosition(npc, PrimaryThreatIndex,_,_, vPredictedPos); + + /* int color[4]; + color[0] = 255; + color[1] = 255; + color[2] = 0; + color[3] = 255; + + int xd = PrecacheModel("materials/sprites/laserbeam.vmt"); + + TE_SetupBeamPoints(vPredictedPos, vecTarget, xd, xd, 0, 0, 0.25, 0.5, 0.5, 5, 5.0, color, 30); + TE_SendToAllInRange(vecTarget, RangeType_Visibility);*/ + + npc.SetGoalVector(vPredictedPos); + } else { + npc.SetGoalEntity(PrimaryThreatIndex); + } + npc.StartPathing(); + + //Target close enough to hit + if(flDistanceToTarget < 22500 || npc.m_flAttackHappenswillhappen) + { + //Look at target so we hit. + // npc.FaceTowards(vecTarget, 2000.0); + + //Can we attack right now? + if(npc.m_flNextMeleeAttack < GetGameTime(npc.index)) + { + //Play attack ani + if (!npc.m_flAttackHappenswillhappen) + { + npc.AddGesture("ACT_MP_ATTACK_STAND_MELEE_ALLCLASS"); + npc.PlayMeleeSound(); + npc.m_flAttackHappens = GetGameTime(npc.index)+0.4; + npc.m_flAttackHappens_bullshit = GetGameTime(npc.index)+0.54; + npc.m_flAttackHappenswillhappen = true; + } + + if (npc.m_flAttackHappens < GetGameTime(npc.index) && npc.m_flAttackHappens_bullshit >= GetGameTime(npc.index) && npc.m_flAttackHappenswillhappen) + { + Handle swingTrace; + npc.FaceTowards(vecTarget, 20000.0); + if(npc.DoSwingTrace(swingTrace, PrimaryThreatIndex,_,_,_,1)) + { + int target = TR_GetEntityIndex(swingTrace); + + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + + if(target > 0) + { + + if(!ShouldNpcDealBonusDamage(target)) + SDKHooks_TakeDamage(target, npc.index, npc.index, 150.0, DMG_CLUB, -1, _, vecHit); + else + SDKHooks_TakeDamage(target, npc.index, npc.index, 1500.0, DMG_CLUB, -1, _, vecHit); + + + Custom_Knockback(npc.index, target, 750.0); + + + // Hit particle + + + // Hit sound + npc.PlayMeleeHitSound(); + } + } + delete swingTrace; + npc.m_flNextMeleeAttack = GetGameTime(npc.index) + 0.8; + npc.m_flAttackHappenswillhappen = false; + } + else if (npc.m_flAttackHappens_bullshit < GetGameTime(npc.index) && npc.m_flAttackHappenswillhappen) + { + npc.m_flAttackHappenswillhappen = false; + npc.m_flNextMeleeAttack = GetGameTime(npc.index) + 0.8; + } + } + } + else if(flDistanceToTarget > 22500 && npc.m_flAttackHappens_2 < GetGameTime(npc.index)) + { + npc.AddGesture("ACT_MP_THROW"); + npc.m_flAttackHappens_2 = GetGameTime(npc.index) + 3.0; + npc.PlayRangedSound(); + npc.FireRocket(vecTarget, 30.0, 600.0); + } + } + else + { + npc.StopPathing(); + + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleAlertSound(); +} + +public Action ZSSoldierGiant_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + ZSSoldierGiant 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 ZSSoldierGiant_ClotDamaged_Post(int victim, int attacker, int inflictor, float damage, int damagetype) +{ + ZSSoldierGiant npc = view_as(victim); + if(!NpcStats_IsEnemySilenced(npc.index)) + { + int maxhealth = ReturnEntityMaxHealth(npc.index); + + float ratio = float(GetEntProp(npc.index, Prop_Data, "m_iHealth")) / float(maxhealth); + if(0.9-(npc.g_TimesSummoned*0.2) > ratio) + { + if(MaxEnemiesAllowedSpawnNext(1) <= (EnemyNpcAlive - EnemyNpcAliveStatic)) + { + fl_TotalArmor[npc.index] = 0.5; + //grrr i cant spawn!!!! + //become fat. + return; + } + fl_TotalArmor[npc.index] = 1.0; + //yay i spawned, im now thinn :3 + npc.g_TimesSummoned++; + maxhealth /= 7; + for(int i; i<1; i++) + { + float pos[3]; GetEntPropVector(npc.index, Prop_Data, "m_vecAbsOrigin", pos); + float ang[3]; GetEntPropVector(npc.index, Prop_Data, "m_angRotation", ang); + + int spawn_index = NPC_CreateByName("npc_zombie_soldier_minion_grave", -1, pos, ang, GetTeam(npc.index)); + if(spawn_index > MaxClients) + { + NpcStats_CopyStats(npc.index, spawn_index); + NpcAddedToZombiesLeftCurrently(spawn_index, true); + SetEntProp(spawn_index, Prop_Data, "m_iHealth", maxhealth); + SetEntProp(spawn_index, Prop_Data, "m_iMaxHealth", maxhealth); + } + } + } + } + else + { + fl_TotalArmor[npc.index] = 1.0; + } +} + +public void ZSSoldierGiant_NPCDeath(int entity) +{ + ZSSoldierGiant npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + SDKUnhook(npc.index, SDKHook_OnTakeDamagePost, ZSSoldierGiant_ClotDamaged_Post); + + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); + if(IsValidEntity(npc.m_iWearable3)) + RemoveEntity(npc.m_iWearable3); + if(IsValidEntity(npc.m_iWearable4)) + RemoveEntity(npc.m_iWearable4); +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_soldier_minion_grave.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_soldier_minion_grave.sp new file mode 100644 index 0000000000..e191cebe44 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_soldier_minion_grave.sp @@ -0,0 +1,354 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + "vo/soldier_paincrticialdeath01.mp3", + "vo/soldier_paincrticialdeath02.mp3", + "vo/soldier_paincrticialdeath03.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_IdleSounds[][] = { + "vo/taunts/soldier_taunts01.mp3", + "vo/taunts/soldier_taunts09.mp3", + "vo/taunts/soldier_taunts14.mp3", + +}; + +static const char g_IdleAlertedSounds[][] = { + "vo/taunts/soldier_taunts19.mp3", + "vo/taunts/soldier_taunts20.mp3", + "vo/taunts/soldier_taunts21.mp3", + "vo/taunts/soldier_taunts18.mp3", +}; + +static const char g_MeleeHitSounds[][] = { + "weapons/boxing_gloves_hit1.wav", + "weapons/boxing_gloves_hit2.wav", + "weapons/boxing_gloves_hit3.wav", + "weapons/boxing_gloves_hit4.wav", +}; +static const char g_MeleeAttackSounds[][] = { + "weapons/boxing_gloves_swing1.wav", + "weapons/boxing_gloves_swing2.wav", + "weapons/boxing_gloves_swing4.wav", +}; + +static const char g_MeleeMissSounds[][] = { + "weapons/bat_draw_swoosh1.wav", + "weapons/bat_draw_swoosh2.wav", +}; + +void ZSSoldierMinion_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_IdleSounds)); i++) { PrecacheSound(g_IdleSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSound(g_IdleAlertedSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeHitSounds)); i++) { PrecacheSound(g_MeleeHitSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeAttackSounds)); i++) { PrecacheSound(g_MeleeAttackSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeMissSounds)); i++) { PrecacheSound(g_MeleeMissSounds[i]); } + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Soldier Minion"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_zs_soldier_minion_grave"); + strcopy(data.Icon, sizeof(data.Icon), "soldier"); + data.IconCustom = false; + data.Flags = 0; + data.Category = Type_Common; + data.Func = ClotSummon; + NPC_Add(data); + +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return ZSSoldierMinion(vecPos, vecAng, team); +} +methodmap ZSSoldierMinion < CClotBody +{ + public void PlayIdleSound() { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + EmitSoundToAll(g_IdleSounds[GetRandomInt(0, sizeof(g_IdleSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(24.0, 48.0); + + + } + + 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_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + public void PlayMeleeHitSound() { + EmitSoundToAll(g_MeleeHitSounds[GetRandomInt(0, sizeof(g_MeleeHitSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + + public void PlayMeleeMissSound() { + EmitSoundToAll(g_MeleeMissSounds[GetRandomInt(0, sizeof(g_MeleeMissSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + public ZSSoldierMinion(float vecPos[3], float vecAng[3], int ally) + { + ZSSoldierMinion npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "10", ally)); + + i_NpcWeight[npc.index] = 1; + + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_MP_RUN_MELEE"); + if(iActivity > 0) npc.StartActivity(iActivity); + + + + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + + func_NPCDeath[npc.index] = ZSSoldierMinion_NPCDeath; + func_NPCOnTakeDamage[npc.index] = ZSSoldierMinion_OnTakeDamage; + func_NPCThink[npc.index] = ZSSoldierMinion_ClotThink; + + //IDLE + npc.m_flSpeed = 330.0; + npc.m_iState = 0; + npc.m_flGetClosestTargetTime = 0.0; + npc.StartPathing(); + + + int skin = 5; + SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); + + npc.m_iWearable1 = npc.EquipItem("head", "models/player/items/soldier/soldier_zombie.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + + npc.m_iWearable2 = npc.EquipItem("head", "models/workshop/weapons/c_models/c_picket/c_picket.mdl"); + SetVariantString("1.0"); + AcceptEntityInput(npc.m_iWearable2, "SetModelScale"); + + SetEntProp(npc.m_iWearable1, Prop_Send, "m_nSkin", 1); + + return npc; + } + + +} + + +public void ZSSoldierMinion_ClotThink(int iNPC) +{ + ZSSoldierMinion 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(); + } + + int PrimaryThreatIndex = npc.m_iTarget; + + if(IsValidEnemy(npc.index, PrimaryThreatIndex, true)) + { + float vecTarget[3]; WorldSpaceCenter(PrimaryThreatIndex, vecTarget); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + + //Predict their pos. + if(flDistanceToTarget < npc.GetLeadRadius()) { + + float vPredictedPos[3]; PredictSubjectPosition(npc, PrimaryThreatIndex,_,_, vPredictedPos); + + /* int color[4]; + color[0] = 255; + color[1] = 255; + color[2] = 0; + color[3] = 255; + + int xd = PrecacheModel("materials/sprites/laserbeam.vmt"); + + TE_SetupBeamPoints(vPredictedPos, vecTarget, xd, xd, 0, 0, 0.25, 0.5, 0.5, 5, 5.0, color, 30); + TE_SendToAllInRange(vecTarget, RangeType_Visibility);*/ + + npc.SetGoalVector(vPredictedPos); + } else { + npc.SetGoalEntity(PrimaryThreatIndex); + } + npc.StartPathing(); + //Target close enough to hit + if(flDistanceToTarget < 7225) + { + //Look at target so we hit. + // npc.FaceTowards(vecTarget, 1000.0); + + //Can we attack right now? + if(npc.m_flNextMeleeAttack < GetGameTime(npc.index)) + { + //Play attack ani + if (!npc.m_flAttackHappenswillhappen) + { + npc.AddGesture("ACT_MP_ATTACK_STAND_MELEE"); + npc.PlayMeleeSound(); + npc.m_flAttackHappens = GetGameTime(npc.index)+0.4; + npc.m_flAttackHappens_bullshit = GetGameTime(npc.index)+0.54; + npc.m_flAttackHappenswillhappen = true; + } + + if (npc.m_flAttackHappens < GetGameTime(npc.index) && npc.m_flAttackHappens_bullshit >= GetGameTime(npc.index) && npc.m_flAttackHappenswillhappen) + { + Handle swingTrace; + npc.FaceTowards(vecTarget, 20000.0); + if(npc.DoSwingTrace(swingTrace, PrimaryThreatIndex)) + { + int target = TR_GetEntityIndex(swingTrace); + + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + + if(target > 0) + { + + if(!ShouldNpcDealBonusDamage(target)) + SDKHooks_TakeDamage(target, npc.index, npc.index, 100.0, DMG_CLUB, -1, _, vecHit); + else + SDKHooks_TakeDamage(target, npc.index, npc.index, 300.0, DMG_CLUB, -1, _, vecHit); + + // Hit particle + + + // Hit sound + npc.PlayMeleeHitSound(); + + //Did we kill them? + int iHealthPost = GetEntProp(target, Prop_Data, "m_iHealth"); + if(iHealthPost <= 0) + { + //Yup, time to celebrate + npc.AddGesture("ACT_MP_GESTURE_FLINCH_CHEST"); + } + } + } + delete swingTrace; + npc.m_flNextMeleeAttack = GetGameTime(npc.index) + 1.0; + npc.m_flAttackHappenswillhappen = false; + } + else if (npc.m_flAttackHappens_bullshit < GetGameTime(npc.index) && npc.m_flAttackHappenswillhappen) + { + npc.m_flAttackHappenswillhappen = false; + npc.m_flNextMeleeAttack = GetGameTime(npc.index) + 1.0; + } + } + } + } + else + { + npc.StopPathing(); + + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleAlertSound(); +} + +public Action ZSSoldierMinion_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + ZSSoldierMinion 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 ZSSoldierMinion_NPCDeath(int entity) +{ + ZSSoldierMinion npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); + if(IsValidEntity(npc.m_iWearable2)) + RemoveEntity(npc.m_iWearable2); +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_headcrab.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_headcrab.sp new file mode 100644 index 0000000000..be79bea4df --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_headcrab.sp @@ -0,0 +1,371 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + "npc/headcrab/die1.wav", + "npc/headcrab/die2.wav" +}; + +static const char g_HurtSound[][] = { + "npc/headcrab/pain1.wav", + "npc/headcrab/pain2.wav", + "npc/headcrab/pain3.wav" +}; + +static const char g_IdleSound[][] = { + "npc/headcrab/alert1.wav", + "npc/headcrab/idle3.wav" +}; + +static const char g_MeleeHitSounds[][] = { + "npc/headcrab/headbite.wav" +}; + +static const char g_MeleeAttackSounds[][] = { + "npc/headcrab/attack1.wav", + "npc/headcrab/attack2.wav", + "npc/headcrab/attack3.wav" +}; + +//static float fl_KamikazeInitiate; +public void ZSMainHeadcrab_OnMapStart_NPC() +{ + PrecacheSoundArray(g_DeathSounds); + PrecacheSoundArray(g_MeleeAttackSounds); + PrecacheSoundArray(g_MeleeHitSounds); + PrecacheSoundArray(g_IdleSound); + PrecacheSoundArray(g_HurtSound); + + PrecacheSound("player/flow.wav"); + PrecacheModel("models/zombie/classic.mdl"); + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Z-Main Headcrab"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_zs_zmain_headcrab"); + strcopy(data.Icon, sizeof(data.Icon), ""); + data.IconCustom = true; + data.Flags = 0; + data.Category = Type_GmodZS; + data.Func = ClotSummon; +// fl_KamikazeInitiate = 0.0; + NPC_Add(data); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return ZSMainHeadcrab(vecPos, vecAng, team); +} + +methodmap ZSMainHeadcrab < CClotBody +{ + public void PlayIdleSound() + { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleSound[GetRandomInt(0, sizeof(g_IdleSound) - 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() + { + EmitSoundToAll(g_HurtSound[GetRandomInt(0, sizeof(g_HurtSound) - 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_AUTO, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME,_); + } + + + property float m_flJumpCooldownZmain + { + public get() { return fl_AbilityOrAttack[this.index][0]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][0] = TempValueForProperty; } + } + property float m_flTryIgnorebuildings + { + public get() { return fl_AbilityOrAttack[this.index][1]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][1] = TempValueForProperty; } + } + + public ZSMainHeadcrab(float vecPos[3], float vecAng[3], int ally) + { + ZSMainHeadcrab npc = view_as(CClotBody(vecPos, vecAng, "models/headcrabclassic.mdl", "1.15", "3000", ally, false)); + + i_NpcWeight[npc.index] = 1; + + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_RUN"); + if(iActivity > 0) npc.StartActivity(iActivity); + KillFeed_SetKillIcon(npc.index, "bread_bite"); + + + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + //IDLE + npc.m_flSpeed = 330.0; + + /* + if(ally == TFTeam_Blue) + { + if(fl_KamikazeInitiate < GetGameTime()) + { + //This is a kamikaze that was newly initiated! + //add new kamikazies whenever possible. + //this needs to happen every tick! + DoGlobalMultiScaling(); + RequestFrame(SpawnZmainsAFew, 0); + + if(!TeleportDiversioToRandLocation(npc.index,_,1750.0, 1250.0)) + { + //incase their random spawn code fails, they'll spawn here. + int Spawner_entity = GetRandomActiveSpawner(); + if(IsValidEntity(Spawner_entity)) + { + float pos[3]; + float ang[3]; + GetEntPropVector(Spawner_entity, Prop_Data, "m_vecOrigin", pos); + GetEntPropVector(Spawner_entity, Prop_Data, "m_angRotation", ang); + TeleportEntity(npc.index, pos, ang, NULL_VECTOR); + } + } + } + fl_KamikazeInitiate = GetGameTime() + 15.0; + } +*/ + + func_NPCDeath[npc.index] = ZSMainHeadcrab_NPCDeath; + func_NPCThink[npc.index] = ZSMainHeadcrab_ClotThink; + func_NPCOnTakeDamage[npc.index] = Generic_OnTakeDamage; + b_AvoidBuildingsAtAllCosts[npc.index] = true; + + npc.StartPathing(); + f_MaxAnimationSpeed[npc.index] = 1.5; + + return npc; + } + +} + + +public void ZSMainHeadcrab_ClotThink(int iNPC) +{ + ZSMainHeadcrab npc = view_as(iNPC); + +// PrintToChatAll("%.f",GetEntPropFloat(view_as(iNPC), Prop_Data, "m_speed")); + + 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.m_blPlayHurtAnimation = false; + if(!npc.m_flAttackHappenswillhappen) + npc.AddGesture("ACT_GESTURE_FLINCH_HEAD", 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(); + } + + // fldistancelimit isnt working for using vector distance, and checking for can see and only buildings + int IsAbuildingNearMe = GetClosestTarget(npc.index,false,200.0,_,_,_, _,true, _,true,true,0.0, .ExtraValidityFunction = Zmain_TryJumpOverBuildings); + + if(IsValidEnemy(npc.index, npc.m_iTarget)) + { + if(i_IsABuilding[npc.m_iTarget] && npc.m_flTryIgnorebuildings > GetGameTime(npc.index)) + { + npc.m_iTarget = GetClosestTarget(npc.index, .IgnoreBuildings = true); + } + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + ZSMainHeadcrab_AnnoyingZmainwalkLogic(npc,GetGameTime(npc.index), flDistanceToTarget, IsAbuildingNearMe); + ZSMainHeadcrab_SelfDefense(npc,GetGameTime(npc.index), npc.m_iTarget, flDistanceToTarget); + if(i_IsABuilding[npc.m_iTarget]) + { + npc.m_iTarget = GetClosestTarget(npc.index, .IgnoreBuildings = true); + npc.m_flTryIgnorebuildings = GetGameTime(npc.index) + 1.0; + } + } + else + { + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleSound(); +} + +void ZSMainHeadcrab_AnnoyingZmainwalkLogic(ZSMainHeadcrab npc, float gameTime, float distance, int IsAbuildingNearMe) +{ + if(npc.m_flTryIgnorebuildings > gameTime || IsValidEntity(IsAbuildingNearMe)) + { + if(!npc.m_flAttackHappens && npc.m_flJumpCooldownZmain < gameTime) + { + if (npc.IsOnGround()) + { + npc.m_flJumpCooldownZmain = gameTime + 2.0; + npc.GetLocomotionInterface().Jump(); + float vel[3]; + npc.GetVelocity(vel); + vel[2] = 400.0; + npc.SetVelocity(vel); + } + } + } + npc.m_bAllowBackWalking = false; + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 10.0)) + { + if(distance < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + } + //Just walk. + return; + } + + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 0.5)) + { + //relatively close, what do ? + //Randomly jump + if(!npc.m_flAttackHappens && npc.m_flJumpCooldownZmain < gameTime) + { + if (npc.IsOnGround()) + { + npc.m_flJumpCooldownZmain = gameTime + 2.0; + npc.GetLocomotionInterface().Jump(); + float vel[3]; + npc.GetVelocity(vel); + vel[2] = 400.0; + npc.SetVelocity(vel); + } + } + + npc.m_bAllowBackWalking = true; + float vBackoffPos[3]; + BackoffFromOwnPositionAndAwayFromEnemy(npc, npc.m_iTarget,_,vBackoffPos, 1); + npc.SetGoalVector(vBackoffPos, true); //update more often, we need it + return; + } + + //relatively close, what do ? + //Randomly jump + if(!npc.m_flAttackHappens && npc.m_flJumpCooldownZmain < gameTime) + { + if (npc.IsOnGround()) + { + npc.m_flJumpCooldownZmain = gameTime + 2.0; + npc.GetLocomotionInterface().Jump(); + float vel[3]; + npc.GetVelocity(vel); + vel[2] = 400.0; + npc.SetVelocity(vel); + } + } + float vBackoffPos[3]; + BackoffFromOwnPositionAndAwayFromEnemy(npc, npc.m_iTarget,_,vBackoffPos, 2); + npc.SetGoalVector(vBackoffPos, true); //update more often, we need it + npc.m_bAllowBackWalking = true; +} + +void ZSMainHeadcrab_SelfDefense(ZSMainHeadcrab npc, float gameTime, int target, float distance) +{ + float VecEnemy[3]; WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 500.0); + if(npc.m_flAttackHappens) + { + if(npc.m_flAttackHappens < gameTime) + { + npc.m_flAttackHappens = 0.0; + + Handle swingTrace; + WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 15000.0); + if(npc.DoSwingTrace(swingTrace, npc.m_iTarget)) //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 = 100.0; + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 5.5; + + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_CLUB, -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_RANGE_ATTACK1"); + + npc.m_flAttackHappens = gameTime + 0.71; + npc.m_flDoingAnimation = gameTime + 0.71; + npc.m_flNextMeleeAttack = gameTime + 1.2; + } + } + } +} + +public void ZSMainHeadcrab_NPCDeath(int entity) +{ + ZSMainHeadcrab npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } +} diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_headcrabzombie.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_headcrabzombie.sp new file mode 100644 index 0000000000..faa54504be --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_headcrabzombie.sp @@ -0,0 +1,425 @@ +#pragma semicolon 1 +#pragma newdecls required + +static char g_DeathSounds[][] = { + "npc/zombie/zombie_die1.wav", + "npc/zombie/zombie_die2.wav", + "npc/zombie/zombie_die3.wav", +}; + +static char g_HurtSounds[][] = { + "npc/zombie/zombie_pain1.wav", + "npc/zombie/zombie_pain2.wav", + "npc/zombie/zombie_pain3.wav", + "npc/zombie/zombie_pain4.wav", + "npc/zombie/zombie_pain5.wav", + "npc/zombie/zombie_pain6.wav", +}; + +static char g_IdleSounds[][] = { + "npc/zombie/zombie_voice_idle1.wav", + "npc/zombie/zombie_voice_idle2.wav", + "npc/zombie/zombie_voice_idle3.wav", + "npc/zombie/zombie_voice_idle4.wav", + "npc/zombie/zombie_voice_idle5.wav", + "npc/zombie/zombie_voice_idle6.wav", + "npc/zombie/zombie_voice_idle7.wav", + "npc/zombie/zombie_voice_idle8.wav", + "npc/zombie/zombie_voice_idle9.wav", + "npc/zombie/zombie_voice_idle10.wav", + "npc/zombie/zombie_voice_idle11.wav", + "npc/zombie/zombie_voice_idle12.wav", + "npc/zombie/zombie_voice_idle13.wav", + "npc/zombie/zombie_voice_idle14.wav", +}; + +static char g_IdleAlertedSounds[][] = { + "npc/zombie/zombie_alert1.wav", + "npc/zombie/zombie_alert2.wav", + "npc/zombie/zombie_alert3.wav", +}; + +static char g_MeleeHitSounds[][] = { + "npc/fast_zombie/claw_strike1.wav", + "npc/fast_zombie/claw_strike2.wav", + "npc/fast_zombie/claw_strike3.wav", +}; +static char g_MeleeAttackSounds[][] = { + "npc/zombie/zo_attack1.wav", + "npc/zombie/zo_attack2.wav", +}; + +static char g_MeleeMissSounds[][] = { + "npc/fast_zombie/claw_miss1.wav", + "npc/fast_zombie/claw_miss2.wav", +}; + +//static float fl_KamikazeInitiate; +public void ZSMainHeadcrabZombie_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_IdleSounds)); i++) { PrecacheSound(g_IdleSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSound(g_IdleAlertedSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeHitSounds)); i++) { PrecacheSound(g_MeleeHitSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeAttackSounds)); i++) { PrecacheSound(g_MeleeAttackSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeMissSounds)); i++) { PrecacheSound(g_MeleeMissSounds[i]); } + + PrecacheSound("player/flow.wav"); + PrecacheModel("models/zombie/classic.mdl"); + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Z-Main"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_zs_zmain_headcrabzombie"); + strcopy(data.Icon, sizeof(data.Icon), "norm_headcrab_zombie"); + data.IconCustom = true; + data.Flags = 0; + data.Category = Type_Mutation; + data.Func = ClotSummon; + NPC_Add(data); +// fl_KamikazeInitiate = 0.0; +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return ZSMainHeadcrabZombie(vecPos, vecAng, team); +} + +methodmap ZSMainHeadcrabZombie < CClotBody +{ + public void PlayIdleSound() { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + EmitSoundToAll(g_IdleSounds[GetRandomInt(0, sizeof(g_IdleSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(3.0, 6.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_VOICE, 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 PlayMeleeMissSound() { + EmitSoundToAll(g_MeleeMissSounds[GetRandomInt(0, sizeof(g_MeleeMissSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + + + } + + + property float m_flJumpCooldownZmain + { + public get() { return fl_AbilityOrAttack[this.index][0]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][0] = TempValueForProperty; } + } + property float m_flTryIgnorebuildings + { + public get() { return fl_AbilityOrAttack[this.index][1]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][1] = TempValueForProperty; } + } + + public ZSMainHeadcrabZombie(float vecPos[3], float vecAng[3], int ally) + { + ZSMainHeadcrabZombie npc = view_as(CClotBody(vecPos, vecAng, "models/zombie/classic.mdl", "1.15", "6000", ally, false)); + + i_NpcWeight[npc.index] = 1; + + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_WALK"); + if(iActivity > 0) npc.StartActivity(iActivity); + + + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + b_thisNpcIsABoss[npc.index] = true; + + //IDLE + npc.m_flSpeed = 330.0; + + float wave = float(Waves_GetRoundScale()+1); //Wave scaling + + wave *= 0.133333; + + npc.m_flWaveScale = wave; + /* + if(ally == TFTeam_Blue) + { + if(fl_KamikazeInitiate < GetGameTime()) + { + //This is a kamikaze that was newly initiated! + //add new kamikazies whenever possible. + //this needs to happen every tick! + DoGlobalMultiScaling(); + RemainingZmainsSpawn = 4; + RequestFrame(SpawnZmainsAFew, 0); + + if(!TeleportDiversioToRandLocation(npc.index,_,1750.0, 1250.0)) + { + //incase their random spawn code fails, they'll spawn here. + int Spawner_entity = GetRandomActiveSpawner(); + if(IsValidEntity(Spawner_entity)) + { + float pos[3]; + float ang[3]; + GetEntPropVector(Spawner_entity, Prop_Data, "m_vecOrigin", pos); + GetEntPropVector(Spawner_entity, Prop_Data, "m_angRotation", ang); + TeleportEntity(npc.index, pos, ang, NULL_VECTOR); + } + } + } + fl_KamikazeInitiate = GetGameTime() + 15.0; + } + */ + + func_NPCDeath[npc.index] = ZSMainHeadcrabZombie_NPCDeath; + func_NPCThink[npc.index] = ZSMainHeadcrabZombie_ClotThink; + func_NPCOnTakeDamage[npc.index] = Generic_OnTakeDamage; + b_AvoidBuildingsAtAllCosts[npc.index] = true; + + npc.StartPathing(); + f_MaxAnimationSpeed[npc.index] = 1.5; + + return npc; + } + +} + + +public void ZSMainHeadcrabZombie_ClotThink(int iNPC) +{ + ZSMainHeadcrabZombie npc = view_as(iNPC); + +// PrintToChatAll("%.f",GetEntPropFloat(view_as(iNPC), Prop_Data, "m_speed")); + + 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.m_blPlayHurtAnimation = false; + if(!npc.m_flAttackHappenswillhappen) + npc.AddGesture("ACT_GESTURE_FLINCH_HEAD", 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(); + } + + // fldistancelimit isnt working for using vector distance, and checking for can see and only buildings + int IsAbuildingNearMe = GetClosestTarget(npc.index,false,200.0,_,_,_, _,true, _,true,true,0.0, .ExtraValidityFunction = Zmain_TryJumpOverBuildings); + + if(IsValidEnemy(npc.index, npc.m_iTarget)) + { + if(i_IsABuilding[npc.m_iTarget] && npc.m_flTryIgnorebuildings > GetGameTime(npc.index)) + { + npc.m_iTarget = GetClosestTarget(npc.index, .IgnoreBuildings = true); + } + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + ZSMainHeadcrabZombie_AnnoyingZmainwalkLogic(npc,GetGameTime(npc.index), flDistanceToTarget, IsAbuildingNearMe); + ZSMainHeadcrabZombie_SelfDefense(npc,GetGameTime(npc.index), npc.m_iTarget, flDistanceToTarget); + if(i_IsABuilding[npc.m_iTarget]) + { + npc.m_iTarget = GetClosestTarget(npc.index, .IgnoreBuildings = true); + npc.m_flTryIgnorebuildings = GetGameTime(npc.index) + 1.0; + } + } + else + { + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleSound(); +} + +void ZSMainHeadcrabZombie_AnnoyingZmainwalkLogic(ZSMainHeadcrabZombie npc, float gameTime, float distance, int IsAbuildingNearMe) +{ + if(npc.m_flTryIgnorebuildings > gameTime || IsValidEntity(IsAbuildingNearMe)) + { + if(!npc.m_flAttackHappens && npc.m_flJumpCooldownZmain < gameTime) + { + if (npc.IsOnGround()) + { + npc.m_flJumpCooldownZmain = gameTime + 2.0; + npc.GetLocomotionInterface().Jump(); + float vel[3]; + npc.GetVelocity(vel); + vel[2] = 400.0; + npc.SetVelocity(vel); + } + } + } + npc.m_bAllowBackWalking = false; + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 10.0)) + { + if(distance < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + } + //Just walk. + return; + } + + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 0.5)) + { + //relatively close, what do ? + //Randomly jump + if(!npc.m_flAttackHappens && npc.m_flJumpCooldownZmain < gameTime) + { + if (npc.IsOnGround()) + { + npc.m_flJumpCooldownZmain = gameTime + 2.0; + npc.GetLocomotionInterface().Jump(); + float vel[3]; + npc.GetVelocity(vel); + vel[2] = 400.0; + npc.SetVelocity(vel); + } + } + + npc.m_bAllowBackWalking = true; + float vBackoffPos[3]; + BackoffFromOwnPositionAndAwayFromEnemy(npc, npc.m_iTarget,_,vBackoffPos, 1); + npc.SetGoalVector(vBackoffPos, true); //update more often, we need it + return; + } + + //relatively close, what do ? + //Randomly jump + if(!npc.m_flAttackHappens && npc.m_flJumpCooldownZmain < gameTime) + { + if (npc.IsOnGround()) + { + npc.m_flJumpCooldownZmain = gameTime + 2.0; + npc.GetLocomotionInterface().Jump(); + float vel[3]; + npc.GetVelocity(vel); + vel[2] = 400.0; + npc.SetVelocity(vel); + } + } + float vBackoffPos[3]; + BackoffFromOwnPositionAndAwayFromEnemy(npc, npc.m_iTarget,_,vBackoffPos, 2); + npc.SetGoalVector(vBackoffPos, true); //update more often, we need it + npc.m_bAllowBackWalking = true; +} + +void ZSMainHeadcrabZombie_SelfDefense(ZSMainHeadcrabZombie npc, float gameTime, int target, float distance) +{ + float VecEnemy[3]; WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 500.0); + if(npc.m_flAttackHappens) + { + if(npc.m_flAttackHappens < gameTime) + { + npc.m_flAttackHappens = 0.0; + + Handle swingTrace; + WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 15000.0); + if(npc.DoSwingTrace(swingTrace, npc.m_iTarget)) //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 = 80.0; + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 5.5; + + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt * npc.m_flWaveScale, DMG_CLUB, -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_MELEE_ATTACK1"); + + npc.m_flAttackHappens = gameTime + 0.71; + npc.m_flDoingAnimation = gameTime + 0.71; + npc.m_flNextMeleeAttack = gameTime + 1.2; + } + } + } +} + +public void ZSMainHeadcrabZombie_NPCDeath(int entity) +{ + ZSMainHeadcrabZombie npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } +} diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_poisonzombie.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_poisonzombie.sp new file mode 100644 index 0000000000..1c60455caf --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_poisonzombie.sp @@ -0,0 +1,483 @@ +#pragma semicolon 1 +#pragma newdecls required + +static char g_DeathSounds[][] = { + "npc/zombie_poison/pz_die1.wav", + "npc/zombie_poison/pz_die2.wav", +}; + +static char g_HurtSounds[][] = { + "npc/zombie_poison/pz_pain1.wav", + "npc/zombie_poison/pz_pain2.wav", + "npc/zombie_poison/pz_pain3.wav", +}; + +static char g_IdleSounds[][] = { + "npc/zombie_poison/pz_idle2.wav", + "npc/zombie_poison/pz_idle3.wav", + "npc/zombie_poison/pz_idle4.wav", +}; + +static char g_IdleAlertedSounds[][] = { + "npc/zombie_poison/pz_alert1.wav", + "npc/zombie_poison/pz_alert2.wav", +}; + +static char g_MeleeHitSounds[][] = { + "npc/fast_zombie/claw_strike1.wav", + "npc/fast_zombie/claw_strike2.wav", + "npc/fast_zombie/claw_strike3.wav", +}; +static char g_MeleeAttackSounds[][] = { + "npc/zombie_poison/pz_warn1.wav", + "npc/zombie_poison/pz_warn2.wav", +}; + +static char g_MeleeMissSounds[][] = { + "npc/fast_zombie/claw_miss1.wav", + "npc/fast_zombie/claw_miss2.wav", +}; + +//static float fl_KamikazeInitiate; +public void ZSMainPoisonZombie_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_IdleSounds)); i++) { PrecacheSound(g_IdleSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSound(g_IdleAlertedSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeHitSounds)); i++) { PrecacheSound(g_MeleeHitSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeAttackSounds)); i++) { PrecacheSound(g_MeleeAttackSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeMissSounds)); i++) { PrecacheSound(g_MeleeMissSounds[i]); } + + PrecacheSound("player/flow.wav"); + PrecacheModel("models/zombie/poison.mdl"); + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Z-Main Poison Zombie"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_zs_zmain_poisonzombie"); + strcopy(data.Icon, sizeof(data.Icon), "norm_poison_zombie"); + data.IconCustom = true; + data.Flags = 0; + data.Category = Type_Mutation; + data.Func = ClotSummon; +// fl_KamikazeInitiate = 0.0; + NPC_Add(data); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return ZSMainPoisonZombie(vecPos, vecAng, team); +} + +methodmap ZSMainPoisonZombie < CClotBody +{ + public void PlayIdleSound() { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleSounds[GetRandomInt(0, sizeof(g_IdleSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(3.0, 6.0); + + + } + + public void PlayIdleAlertSound() { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + + EmitSoundToAll(g_IdleAlertedSounds[GetRandomInt(0, sizeof(g_IdleAlertedSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(3.0, 6.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_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + + } + + public void PlayMeleeSound() { + EmitSoundToAll(g_MeleeAttackSounds[GetRandomInt(0, sizeof(g_MeleeAttackSounds) - 1)], this.index, SNDCHAN_VOICE, 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 PlayMeleeMissSound() { + EmitSoundToAll(g_MeleeMissSounds[GetRandomInt(0, sizeof(g_MeleeMissSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + + } + + + property float m_flJumpCooldownZmain + { + public get() { return fl_AbilityOrAttack[this.index][0]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][0] = TempValueForProperty; } + } + property float m_flTryIgnorebuildings + { + public get() { return fl_AbilityOrAttack[this.index][1]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][1] = TempValueForProperty; } + } + + public ZSMainPoisonZombie(float vecPos[3], float vecAng[3], int ally) + { + ZSMainPoisonZombie npc = view_as(CClotBody(vecPos, vecAng, "models/zombie/poison.mdl", "1.15", "5000", ally, false)); + + i_NpcWeight[npc.index] = 1; + + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_WALK"); + if(iActivity > 0) npc.StartActivity(iActivity); + KillFeed_SetKillIcon(npc.index, "infection_heavy"); + + + npc.m_flNextMeleeAttack = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_NORMAL; + + //IDLE + npc.m_flSpeed = 330.0; + + float wave = float(Waves_GetRoundScale()+1); //Wave scaling + + wave *= 0.133333; + + npc.m_flWaveScale = wave; + + /* + if(ally == TFTeam_Blue) + { + if(fl_KamikazeInitiate < GetGameTime()) + { + //This is a kamikaze that was newly initiated! + //add new kamikazies whenever possible. + //this needs to happen every tick! + DoGlobalMultiScaling(); + RequestFrame(SpawnZmainsAFew, 0); + + if(!TeleportDiversioToRandLocation(npc.index,_,1750.0, 1250.0)) + { + //incase their random spawn code fails, they'll spawn here. + int Spawner_entity = GetRandomActiveSpawner(); + if(IsValidEntity(Spawner_entity)) + { + float pos[3]; + float ang[3]; + GetEntPropVector(Spawner_entity, Prop_Data, "m_vecOrigin", pos); + GetEntPropVector(Spawner_entity, Prop_Data, "m_angRotation", ang); + TeleportEntity(npc.index, pos, ang, NULL_VECTOR); + } + } + } + fl_KamikazeInitiate = GetGameTime() + 15.0; + } +*/ + func_NPCDeath[npc.index] = ZSMainPoisonZombie_NPCDeath; + func_NPCThink[npc.index] = ZSMainPoisonZombie_ClotThink; + func_NPCOnTakeDamage[npc.index] = Generic_OnTakeDamage; + b_AvoidBuildingsAtAllCosts[npc.index] = true; + + npc.StartPathing(); + f_MaxAnimationSpeed[npc.index] = 1.5; + + return npc; + } + +} + + +public void ZSMainPoisonZombie_ClotThink(int iNPC) +{ + ZSMainPoisonZombie npc = view_as(iNPC); + +// PrintToChatAll("%.f",GetEntPropFloat(view_as(iNPC), Prop_Data, "m_speed")); + + 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.m_blPlayHurtAnimation = false; + if(!npc.m_flAttackHappenswillhappen) + npc.AddGesture("ACT_GESTURE_FLINCH_HEAD", 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(); + } + + // fldistancelimit isnt working for using vector distance, and checking for can see and only buildings + int IsAbuildingNearMe = GetClosestTarget(npc.index,false,200.0,_,_,_, _,true, _,true,true,0.0, .ExtraValidityFunction = Zmain_TryJumpOverBuildings); + + if(IsValidEnemy(npc.index, npc.m_iTarget)) + { + if(i_IsABuilding[npc.m_iTarget] && npc.m_flTryIgnorebuildings > GetGameTime(npc.index)) + { + npc.m_iTarget = GetClosestTarget(npc.index, .IgnoreBuildings = true); + } + float vecTarget[3]; WorldSpaceCenter(npc.m_iTarget, vecTarget ); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + ZSMainPoisonZombie_AnnoyingZmainwalkLogic(npc,GetGameTime(npc.index), flDistanceToTarget, IsAbuildingNearMe); + ZSMainPoisonZombie_SelfDefense(npc,GetGameTime(npc.index), npc.m_iTarget, flDistanceToTarget); + if(i_IsABuilding[npc.m_iTarget]) + { + npc.m_iTarget = GetClosestTarget(npc.index, .IgnoreBuildings = true); + npc.m_flTryIgnorebuildings = GetGameTime(npc.index) + 1.0; + } + } + else + { + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleSound(); +} + +void ZSMainPoisonZombie_AnnoyingZmainwalkLogic(ZSMainPoisonZombie npc, float gameTime, float distance, int IsAbuildingNearMe) +{ + if(npc.m_flTryIgnorebuildings > gameTime || IsValidEntity(IsAbuildingNearMe)) + { + if(!npc.m_flAttackHappens && npc.m_flJumpCooldownZmain < gameTime) + { + if (npc.IsOnGround()) + { + npc.m_flJumpCooldownZmain = gameTime + 2.0; + npc.GetLocomotionInterface().Jump(); + float vel[3]; + npc.GetVelocity(vel); + vel[2] = 400.0; + npc.SetVelocity(vel); + } + } + } + npc.m_bAllowBackWalking = false; + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 10.0)) + { + if(distance < npc.GetLeadRadius()) + { + float vPredictedPos[3]; + PredictSubjectPosition(npc, npc.m_iTarget,_,_, vPredictedPos); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(npc.m_iTarget); + } + //Just walk. + return; + } + + if(distance > (NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED * 0.5)) + { + //relatively close, what do ? + //Randomly jump + if(!npc.m_flAttackHappens && npc.m_flJumpCooldownZmain < gameTime) + { + if (npc.IsOnGround()) + { + npc.m_flJumpCooldownZmain = gameTime + 2.0; + npc.GetLocomotionInterface().Jump(); + float vel[3]; + npc.GetVelocity(vel); + vel[2] = 400.0; + npc.SetVelocity(vel); + } + } + + npc.m_bAllowBackWalking = true; + float vBackoffPos[3]; + BackoffFromOwnPositionAndAwayFromEnemy(npc, npc.m_iTarget,_,vBackoffPos, 1); + npc.SetGoalVector(vBackoffPos, true); //update more often, we need it + return; + } + + //relatively close, what do ? + //Randomly jump + if(!npc.m_flAttackHappens && npc.m_flJumpCooldownZmain < gameTime) + { + if (npc.IsOnGround()) + { + npc.m_flJumpCooldownZmain = gameTime + 2.0; + npc.GetLocomotionInterface().Jump(); + float vel[3]; + npc.GetVelocity(vel); + vel[2] = 400.0; + npc.SetVelocity(vel); + } + } + float vBackoffPos[3]; + BackoffFromOwnPositionAndAwayFromEnemy(npc, npc.m_iTarget,_,vBackoffPos, 2); + npc.SetGoalVector(vBackoffPos, true); //update more often, we need it + npc.m_bAllowBackWalking = true; +} + +void ZSMainPoisonZombie_SelfDefense(ZSMainPoisonZombie npc, float gameTime, int target, float distance) +{ + float VecEnemy[3]; WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 500.0); + if(npc.m_flAttackHappens) + { + if(npc.m_flAttackHappens < gameTime) + { + npc.m_flAttackHappens = 0.0; + + Handle swingTrace; + WorldSpaceCenter(npc.m_iTarget, VecEnemy); + npc.FaceTowards(VecEnemy, 15000.0); + if(npc.DoSwingTrace(swingTrace, npc.m_iTarget)) //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 = 160.0; + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 5.5; + + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt * npc.m_flWaveScale, DMG_CLUB, -1, _, vecHit); + Elemental_AddPheromoneDamage(target, npc.index, npc.index ? 50 : 10); + + // 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_MELEE_ATTACK1"); + + npc.m_flAttackHappens = gameTime + 0.71; + npc.m_flDoingAnimation = gameTime + 0.71; + npc.m_flNextMeleeAttack = gameTime + 1.2; + } + } + } +} + +public Action ZSMainPoisonZombie_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + //Valid attackers only. + if(attacker <= 0) + return Plugin_Continue; + + ZSMainPoisonZombie npc = view_as(victim); + if(!NpcStats_IsEnemySilenced(victim)) + { + if(!npc.bXenoInfectedSpecialHurt) + { + npc.bXenoInfectedSpecialHurt = true; + npc.flXenoInfectedSpecialHurtTime = GetGameTime(npc.index) + 2.0; + SetEntityRenderMode(npc.index, RENDER_TRANSCOLOR); + SetEntityRenderColor(npc.index, 150, 255, 150, 65); + CreateTimer(2.0, ZSMainPoisonZombie_Revert_Poison_Zombie_Resistance, EntIndexToEntRef(victim), TIMER_FLAG_NO_MAPCHANGE); + CreateTimer(10.0, ZSMainPoisonZombie_Revert_Poison_Zombie_Resistance_Enable, EntIndexToEntRef(victim), TIMER_FLAG_NO_MAPCHANGE); + } + float TrueArmor = 1.0; + if(!NpcStats_IsEnemySilenced(victim)) + { + if(fl_TotalArmor[npc.index] == 1.0) + { + if(npc.flXenoInfectedSpecialHurtTime > GetGameTime(npc.index)) + { + TrueArmor *= 0.25; + fl_TotalArmor[npc.index] = TrueArmor; + OnTakeDamageNpcBaseArmorLogic(victim, attacker, damage, damagetype, true); + } + } + } + fl_TotalArmor[npc.index] = TrueArmor; + } + + /* + if(attacker > MaxClients && !IsValidEnemy(npc.index, attacker)) + 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 Action ZSMainPoisonZombie_Revert_Poison_Zombie_Resistance(Handle timer, int ref) +{ + int zombie = EntRefToEntIndex(ref); + if(IsValidEntity(zombie)) + { + SetEntityRenderMode(zombie, RENDER_NORMAL); + SetEntityRenderColor(zombie, 255, 255, 255, 255); + } + return Plugin_Handled; +} + +public Action ZSMainPoisonZombie_Revert_Poison_Zombie_Resistance_Enable(Handle timer, int ref) +{ + int zombie = EntRefToEntIndex(ref); + if(IsValidEntity(zombie)) + { + ZSMainPoisonZombie npc = view_as(zombie); + npc.bXenoInfectedSpecialHurt = false; + } + return Plugin_Handled; +} + +public void ZSMainPoisonZombie_NPCDeath(int entity) +{ + ZSMainPoisonZombie npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } +} \ No newline at end of file diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zombine.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zombine.sp new file mode 100644 index 0000000000..f4ecf5d300 --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zombine.sp @@ -0,0 +1,354 @@ +#pragma semicolon 1 +#pragma newdecls required + +static char g_DeathSounds[][] = { + "npc/zombine/zombine_die1.wav", +}; + +static char g_HurtSounds[][] = { + "npc/zombine/zombine_pain1.wav", + "npc/zombine/zombine_pain2.wav", + "npc/zombine/zombine_pain3.wav", + "npc/zombine/zombine_pain4.wav", +}; + +static char g_IdleSounds[][] = { + "npc/zombine/zombine_idle1.wav", + "npc/zombine/zombine_idle2.wav", + "npc/zombine/zombine_idle3.wav", + "npc/zombine/zombine_idle4.wav", + "npc/zombine/zombine_alert1.wav", + "npc/zombine/zombine_alert2.wav", + "npc/zombine/zombine_alert3.wav", + "npc/zombine/zombine_alert4.wav", + "npc/zombine/zombine_alert5.wav", + "npc/zombine/zombine_alert6.wav", + "npc/zombine/zombine_alert7.wav", +}; + +static char g_IdleAlertedSounds[][] = { + "npc/zombine/zombine_idle1.wav", + "npc/zombine/zombine_idle2.wav", + "npc/zombine/zombine_idle3.wav", + "npc/zombine/zombine_idle4.wav", + "npc/zombine/zombine_alert1.wav", + "npc/zombine/zombine_alert2.wav", + "npc/zombine/zombine_alert3.wav", + "npc/zombine/zombine_alert4.wav", + "npc/zombine/zombine_alert5.wav", + "npc/zombine/zombine_alert6.wav", + "npc/zombine/zombine_alert7.wav", +}; + +static char g_MeleeHitSounds[][] = { + "npc/fast_zombie/claw_strike1.wav", + "npc/fast_zombie/claw_strike2.wav", + "npc/fast_zombie/claw_strike3.wav", +}; +static char g_MeleeAttackSounds[][] = { + "npc/zombine/zombine_charge1.wav", + "npc/zombine/zombine_charge2.wav", +}; + +static char g_MeleeMissSounds[][] = { + "npc/fast_zombie/claw_miss1.wav", + "npc/fast_zombie/claw_miss2.wav", +}; +static const char g_HurtArmorSounds[][] = { + ")physics/metal/metal_box_impact_bullet1.wav", + ")physics/metal/metal_box_impact_bullet2.wav", + ")physics/metal/metal_box_impact_bullet3.wav", +}; + +public void ZSZombine_OnMapStart_NPC() +{ + for (int i = 0; i < (sizeof(g_MeleeHitSounds)); i++) { PrecacheSound(g_MeleeHitSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeMissSounds)); i++) { PrecacheSound(g_MeleeMissSounds[i]); } + for (int i = 0; i < (sizeof(g_HurtArmorSounds)); i++) { PrecacheSound(g_HurtArmorSounds[i]); } + +// g_iPathLaserModelIndex = PrecacheModel("materials/sprites/laserbeam.vmt"); + NPCData data; + strcopy(data.Name, sizeof(data.Name), "Zombine"); + strcopy(data.Plugin, sizeof(data.Plugin), "npc_zs_zombine"); + strcopy(data.Icon, sizeof(data.Icon), ""); + data.IconCustom = false; + data.Flags = 0; + data.Category = Type_Mutation; + data.Func = ClotSummon; + data.Precache = ClotPrecache; + NPC_Add(data); +} +static void ClotPrecache() +{ + PrecacheModel("models/zombie/zombie_soldier.mdl"); + for (int i = 0; i < (sizeof(g_DeathSounds)); i++) { PrecacheSoundCustom(g_DeathSounds[i]); } + for (int i = 0; i < (sizeof(g_HurtSounds)); i++) { PrecacheSoundCustom(g_HurtSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleSounds)); i++) { PrecacheSoundCustom(g_IdleSounds[i]); } + for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSoundCustom(g_IdleAlertedSounds[i]); } + for (int i = 0; i < (sizeof(g_MeleeAttackSounds)); i++) { PrecacheSoundCustom(g_MeleeAttackSounds[i]); } +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return ZSZombine(vecPos, vecAng, team); +} + +methodmap ZSZombine < CClotBody +{ + public void PlayIdleSound() { + if(this.m_flNextIdleSound > GetGameTime(this.index)) + return; + EmitCustomToAll(g_IdleSounds[GetRandomInt(0, sizeof(g_IdleSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + this.m_flNextIdleSound = GetGameTime(this.index) + GetRandomFloat(3.0, 6.0); + + } + + public void PlayHurtSound() { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + + EmitCustomToAll(g_HurtSounds[GetRandomInt(0, sizeof(g_HurtSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + + } + + public void PlayDeathSound() { + + EmitCustomToAll(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_VOICE, 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 PlayMeleeMissSound() { + EmitSoundToAll(g_MeleeMissSounds[GetRandomInt(0, sizeof(g_MeleeMissSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + } + public void PlayHurtArmorSound() + { + if(this.m_flNextHurtSound > GetGameTime(this.index)) + return; + + this.m_flNextHurtSound = GetGameTime(this.index) + 0.4; + EmitSoundToAll(g_HurtArmorSounds[GetRandomInt(0, sizeof(g_HurtArmorSounds) - 1)], this.index, SNDCHAN_STATIC, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME); + + } + + + public ZSZombine(float vecPos[3], float vecAng[3], int ally) + { + ZSZombine npc = view_as(CClotBody(vecPos, vecAng, "models/zombie/zombie_soldier.mdl", "1.3", "20000", ally, false)); + + i_NpcWeight[npc.index] = 2; + + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_RUN"); + if(iActivity > 0) npc.StartActivity(iActivity); + SetVariantInt(1); + AcceptEntityInput(npc.index, "SetBodyGroup"); + + npc.m_flNextMeleeAttack = 0.0; + npc.m_flAbilityOrAttack0 = 0.0; + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_COMBINE; + + //IDLE + npc.m_flSpeed = 330.0; + + func_NPCDeath[npc.index] = ZSZombine_NPCDeath; + func_NPCThink[npc.index] = ZSZombine_ClotThink; + func_NPCOnTakeDamage[npc.index] = ZSZombine_OnTakeDamage; + + npc.StartPathing(); + + return npc; + } + +} + + +public void ZSZombine_ClotThink(int iNPC) +{ + ZSZombine npc = view_as(iNPC); + + float gameTime = GetGameTime(npc.index); + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) + { + return; + } + if(npc.m_flAbilityOrAttack0 < gameTime) + { + npc.m_flAbilityOrAttack0 = gameTime + 0.5; + int target = GetClosestAlly(npc.index, (250.0 * 250.0), _); + if(target && !b_thisNpcIsARaid[target]) + { + + GrantEntityArmor(target, true, 0.5, 0.5, 0); + ChaosSupporter npc1 = view_as(npc.index); + float ProjectileLoc[3]; + GetEntPropVector(npc1.index, Prop_Data, "m_vecAbsOrigin", ProjectileLoc); + spawnRing_Vectors(ProjectileLoc, 1.0, 0.0, 0.0, 10.0, "materials/sprites/laserbeam.vmt", 150, 150, 0, 200, 1, 0.3, 5.0, 8.0, 3, 40.0 * 2.0); + } + } + + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + + npc.Update(); + + if(npc.m_blPlayHurtAnimation) + { + npc.m_blPlayHurtAnimation = false; + if(!npc.m_flAttackHappenswillhappen) + npc.AddGesture("ACT_GESTURE_FLINCH_HEAD", 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(); + npc.StartPathing(); + //PluginBot_NormalJump(npc.index); + } + + int closest = npc.m_iTarget; + + if(IsValidEnemy(npc.index, closest)) + { + float vecTarget[3]; WorldSpaceCenter(closest, vecTarget); + + float VecSelfNpc[3]; WorldSpaceCenter(npc.index, VecSelfNpc); + float flDistanceToTarget = GetVectorDistance(vecTarget, VecSelfNpc, true); + + //Predict their pos. + if(flDistanceToTarget < npc.GetLeadRadius()) + { + float vPredictedPos[3]; PredictSubjectPosition(npc, closest,_,_, vPredictedPos); + // PrintToChatAll("cutoff"); + npc.SetGoalVector(vPredictedPos); + } + else + { + npc.SetGoalEntity(closest); + } + + //Target close enough to hit + + if(flDistanceToTarget < NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED || npc.m_flAttackHappenswillhappen) + { + //Look at target so we hit. + // npc.FaceTowards(vecTarget, 20000.0); + + if(npc.m_flNextMeleeAttack < GetGameTime(npc.index)) + { + //Play attack ani + if (!npc.m_flAttackHappenswillhappen) + { + npc.AddGesture("ACT_ZOMBINE_ATTACK_FAST"); + npc.PlayMeleeSound(); + npc.m_flAttackHappens = GetGameTime(npc.index)+0.3; + npc.m_flAttackHappens_bullshit = GetGameTime(npc.index)+0.43; + npc.m_flAttackHappenswillhappen = true; + } + //Can we attack right now? + if (npc.m_flAttackHappens < GetGameTime(npc.index) && npc.m_flAttackHappens_bullshit >= GetGameTime(npc.index) && npc.m_flAttackHappenswillhappen) + { + Handle swingTrace; + npc.FaceTowards(vecTarget, 20000.0); + if(npc.DoSwingTrace(swingTrace, closest)) + { + int target = TR_GetEntityIndex(swingTrace); + float vecHit[3]; + TR_GetEndPosition(vecHit, swingTrace); + if(target > 0) + { + float damageDealt = 50.0; + if(ShouldNpcDealBonusDamage(target)) + damageDealt *= 5.5; + + + SDKHooks_TakeDamage(target, npc.index, npc.index, damageDealt, DMG_CLUB, -1, _, vecHit); + + // Hit sound + npc.PlayMeleeHitSound(); + } + else + { + npc.PlayMeleeMissSound(); + } + } + delete swingTrace; + npc.m_flNextMeleeAttack = GetGameTime(npc.index) + 0.8; + npc.m_flAttackHappenswillhappen = false; + } + else if (npc.m_flAttackHappens_bullshit < GetGameTime(npc.index) && npc.m_flAttackHappenswillhappen) + { + npc.m_flAttackHappenswillhappen = false; + npc.m_flNextMeleeAttack = GetGameTime(npc.index) + 0.8; + } + } + + } + } + else + { + npc.StopPathing(); + + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleSound(); +} + +public void ZSZombine_NPCDeath(int entity) +{ + ZSZombine npc = view_as(entity); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } +} + + +public Action ZSZombine_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom) +{ + ZSZombine npc = view_as(victim); + + if(attacker <= 0) + return Plugin_Continue; + + if(npc.m_flArmorCount > 0.0) + { + + } + else + { + if (npc.m_flHeadshotCooldown < GetGameTime(npc.index)) + { + npc.m_flHeadshotCooldown = GetGameTime(npc.index) + DEFAULT_HURTDELAY; + npc.m_blPlayHurtAnimation = true; + } + } + + + + return Plugin_Changed; +} \ No newline at end of file diff --git a/addons/sourcemod/translations/zombieriot.phrases.icons.txt b/addons/sourcemod/translations/zombieriot.phrases.icons.txt index 53a71303b2..34f2db6801 100644 --- a/addons/sourcemod/translations/zombieriot.phrases.icons.txt +++ b/addons/sourcemod/translations/zombieriot.phrases.icons.txt @@ -732,4 +732,9 @@ "en" "An Infected Messenger Spawned has appeared." "ko" "감염된 전령병이 등장했습니다." } + "Bandits Spawned" + { + "en" "The bandits appeared." + "ko" "밴딧들이 나타났습니다." + } } diff --git a/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt b/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt index b161e614ba..a868576e0e 100644 --- a/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt +++ b/addons/sourcemod/translations/zombieriot.phrases.zombienames.txt @@ -8110,10 +8110,10 @@ "en" "Infected Bread Monster" "ko" "감염된 빵괴물" } - "The neighborhood tough guy" + "Bandit Elite" { - "en" "The neighborhood tough guy" - "ko" "동네힘쎈사람" + "en" "Bandit Elite" + "ko" "엘리트 밴딧" } "Vile Poison Zombie" { @@ -8155,6 +8155,26 @@ "en" "Mass Shooting Lover Marine" "ko" "총 기난사가너무좋아 해병" } + "Headcrab Mill Operator" + { + "en" "Headcrab Mill Operator" + "ko" "헤드크랩 장수" + } + "Angry Headcrab" + { + "en" "Angry Headcrab" + "ko" "개빡친 헤드크랩" + } + "Manhattan Parrot" + { + "en" "Manhattan Parrot" + "ko" "맨해튼 앵무새" + } + "Infected Tomislav Main" + { + "en" "Infected Tomislav Main" + "ko" "감염된 토미건 메인" + } "Pheromone Elemental Damage" { "en" "Pheromone Elemental Damage"