From fe59c0b492e6e87c80dbf9c2462dcbcef118a744 Mon Sep 17 00:00:00 2001 From: Klajsdop Date: Sun, 8 Feb 2026 14:52:46 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=ED=8C=A8=EC=B9=98=EB=82=B4=EC=9A=A9=20-=20?= =?UTF-8?q?gmod=5Fzs=20=EC=97=90=20=EC=9E=88=EB=8A=94=20npc=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EB=93=A4=EC=9D=80=20=EA=B7=B8=EB=83=A5=20=EB=8D=AE?= =?UTF-8?q?=EC=96=B4=EC=94=8C=EC=9A=B0=EC=8B=9C=EB=A9=B4=20=EB=90=98?= =?UTF-8?q?=EC=97=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 피해량은 따로 말 없으면 사람 대상 피해량 1. 종합 페로몬 원소피해로 나오는 하수인들 체력이 최대 3만을 넘지 않게 수정 일부 적들 진영이 GmodZS가 아닌 다른 진영으로 되어 있던 현상 수정 2. 좀비들 감염된 헌츠맨 사거리 증가 감염된 카미가제 데모맨의 자폭 피해량 125 -> 200 감염된 병수도 스나이퍼가 적에게 페로몬 원소피해를 입히게 변경되었고 피해량 160 -> 200 감염된 로켓사수가 가끔 ai가 맛탱이 가서 스폰에서 가만히 잠수타던 이슈가 아마도 해결 말살자 피해량 175 -> 200 감염된 소방관 피해량: 150 -> 175 20~40 라인 좀비들의 전반적인 체력 상향 감염된 유해물질 수집가의 피해량: 100 -> 175 감염된 유해물질 수집가의 구조물 피해량: 550 -> 500 감염된 유해물질 수집가의 적 이속 감소량: 50% -> 90% 감염된 메딕 메인 피해량: 100 -> 175 이에 따라 구조물 피해량도 증가함 총 기난사가너무좋아 해병이 적에게 치명상 디버프를 입힘 총 기난사가너무좋아 해병의 사거리 증가 석기시대 제작자 피해량: 135 -> 200 석기시대 제작자의 사거리 증가 감염된 전령병의 아군 소환이 최대 체력의 25% -> 50%로 변경됨 카오스 파이로가 적에게 트루 데미지를 입힘 오염된 포이즌 좀비 피해량: 380 -> 400 오염된 포이즌 좀비 건물 피해량: 720 -> 1000 오염된 포이즌 좀비 색깔이 지워지던 현상 수정 감염된 빵괴물 이동속도: 260 -> 299 폭주시 이동속도: 520 -> 550 감염된 닌자 스파이의 가면이 멀리서도 보이던 현상 수정 3. 보스 역병 전파자의 광역 공격이 적에게 출혈 피해를 입힘 바스타르자인, 도살자, 레드 머로우의 피해량이 웨이브 스케일링 영향을 받음(7웨이브 전까진 피해량이 오히려 내려감) 둥지가 기존보다 더 빠른 속도로 감염체들을 생산함 거대 포이즌 좀비의 체력이 더 올라 갔고 일반 포이즌 좀비와 동일한 패시브를 가짐(피격시 2초간 저항 증가) 레드 머로우의 체력이 10% 이하로 떨어질 경우 더이상 무적을 쓰지 않음(선입력 된 무적이면 한번 정도 사용함) 레드 머로우는 이제 크리퍼와 동일하게 살아남아 있어도 다음 웨이브로 넘어감 z메인들이 더 이상 랜덤보스로 나오지 않음 불결한 자때 나오는 랜덤보스는 거대 포이즌 좀비, 내 다리 내놔!, 바스타르자인, 도살자, 역병 전파자, 하우러, 좀바인, 본매쉬로 바뀜 4. 레이드 보스 나이트메어, 프레그넌트, 스핑크스가 스폰될때 이제 해당 개체 스폰쪽을 바라보지 않음 프레그넌트가 일반 포이즌 좀비의 패시브를 받음 프레그넌트의 건물 피해량: 1200 -> 2500 다스 고르통보호기 메딕의 광폭화 시간: 300 -> 400 다스 고르통보호기 메딕의 하수인이 더 늘어남 다스 고르통보호기 메딕이 하수인을 소환할때 마다 광폭화 시간을 추가로 30초를 더 줌 다스 고르통보호기 메딕과 불결한 자때 lms가 터질 경우 광폭화 시간을 10초 더 줌 불결한 자의 체력이 25%가 되었을때 소환하는 하수인들의 체력이 최대 20만을 넘지 않게 변경 5. 웨이브 셋 9 웨이브마다 Z메인들이 나옴 그외 후반 웨이브 몹들이 비정상적으로 수십마리가 나오던 현상 수정됨 특정 웨이브에 밴딧 무리가 출현함 6. 맨해튼 앵무새, 헤드크랩 장수가 일반 좀비로 추가됨 7. 좀바인이 주변 좀비들에게 지속적으로 아머를 지급함(레이드 보스 제외) 8. 아군 새대가리 솔저가 아군을 향해서 움직일때 몸을 돌리도록 수정함 9. 아군 새대가리 스나이퍼의 공격 판정이 더 빨리 이루어짐(아마도) 10. 불결한 자 브금 안나오는거 아마도 고쳐짐 --- .../sourcemod/configs/zombie_riot/fast_zs.cfg | 458 ++++++++++------- .../scripting/zombie_riot/elemental.sp | 4 + addons/sourcemod/scripting/zombie_riot/npc.sp | 22 + .../npc/gmod_zs/15/npc_zs_headcrab.sp | 2 +- .../npc/gmod_zs/30/npc_zs_fast_headcrab.sp | 2 +- .../npc/gmod_zs/30/npc_zs_spitter.sp | 13 +- .../npc/gmod_zs/45/npc_angryheadcrab.sp | 245 +++++++++ .../gmod_zs/45/npc_infected_tomislav_main.sp | 284 ++++++++++ .../zombie_riot/npc/gmod_zs/45/npc_zs_hmo.sp | 482 +++++++++++++++++ .../npc/gmod_zs/45/npc_zs_huntsman.sp | 6 +- .../npc/gmod_zs/45/npc_zs_kamikaze_demo.sp | 4 +- .../npc/gmod_zs/45/npc_zs_medic_healer.sp | 4 +- .../npc/gmod_zs/45/npc_zs_ninja_zombie_spy.sp | 3 + .../gmod_zs/45/npc_zs_zombie_demoknight.sp | 6 +- .../npc/gmod_zs/45/npc_zs_zombie_engineer.sp | 4 +- .../npc/gmod_zs/45/npc_zs_zombie_heavy.sp | 2 +- .../npc/gmod_zs/45/npc_zs_zombie_scout.sp | 2 +- .../gmod_zs/45/npc_zs_zombie_sniper_jarate.sp | 5 +- .../npc/gmod_zs/45/npc_zs_zombie_soldier.sp | 99 ++-- .../45/npc_zs_zombie_soldier_pickaxe.sp | 2 +- .../npc/gmod_zs/60/npc_zs_cleaner.sp | 2 +- .../60/npc_zs_combine_soldier_elite.sp | 72 ++- .../npc/gmod_zs/60/npc_zs_eradicator.sp | 4 +- .../npc/gmod_zs/60/npc_zs_firefighter.sp | 2 +- .../zombie_riot/npc/gmod_zs/60/npc_zs_ihbc.sp | 10 +- .../npc/gmod_zs/60/npc_zs_manhattan_parrot.sp | 383 ++++++++++++++ .../npc/gmod_zs/60/npc_zs_medic_main.sp | 6 +- .../zombie_riot/npc/gmod_zs/60/npc_zs_mlsm.sp | 5 +- .../zombie_riot/npc/gmod_zs/60/npc_zs_sam.sp | 9 +- .../gmod_zs/60/npc_zs_soldier_messenger.sp | 5 +- .../npc/gmod_zs/60/npc_zs_stranger.sp | 6 +- .../60/npc_zs_vile_poisonheadcrab_zombie.sp | 12 +- .../gmod_zs/60/npc_zs_zombie_breadmonster.sp | 6 +- .../npc/gmod_zs/60/npc_zs_zombie_fatscout.sp | 2 +- .../npc/gmod_zs/60/npc_zs_zombie_fatspy.sp | 2 +- .../gmod_zs/bosses/npc_doctor_unclean_one.sp | 50 +- .../npc/gmod_zs/bosses/npc_major_vulture.sp | 3 + .../npc/gmod_zs/bosses/npc_zs_nightmare.sp | 3 - .../npc/gmod_zs/bosses/npc_zs_pregnant.sp | 55 +- .../gmod_zs/bosses/npc_zs_soldier_barrager.sp | 23 +- .../npc/gmod_zs/bosses/npc_zs_sphynx.sp | 12 +- .../npc/gmod_zs/bosses/npc_zs_unspeakable.sp | 87 ++-- .../npc/gmod_zs/npc_zs_ally_heavy.sp | 5 + .../npc/gmod_zs/npc_zs_ally_medic.sp | 6 +- .../npc/gmod_zs/npc_zs_ally_sniper.sp | 9 +- .../npc/gmod_zs/npc_zs_ally_soldier.sp | 231 +++++---- .../npc/gmod_zs/special/npc_random_poyo.sp | 160 ++++++ .../npc/gmod_zs/special/npc_random_zombie.sp | 20 +- .../gmod_zs/special/npc_zs_amplification.sp | 3 +- .../npc/gmod_zs/special/npc_zs_bastardzine.sp | 9 +- .../npc/gmod_zs/special/npc_zs_butcher.sp | 12 +- .../gmod_zs/special/npc_zs_flesh_creeper.sp | 1 - .../special/npc_zs_malfunctioning_heavy.sp | 51 +- .../npc/gmod_zs/special/npc_zs_nest.sp | 24 +- .../npc_zs_poisonzombie_fortified_giant.sp | 54 +- .../npc/gmod_zs/special/npc_zs_red_marrow.sp | 22 +- .../special/npc_zs_soldier_giant_grave.sp | 429 ++++++++++++++++ .../special/npc_zs_soldier_minion_grave.sp | 354 +++++++++++++ .../gmod_zs/special/npc_zs_zmain_headcrab.sp | 371 ++++++++++++++ .../special/npc_zs_zmain_headcrabzombie.sp | 425 +++++++++++++++ .../special/npc_zs_zmain_poisonzombie.sp | 483 ++++++++++++++++++ .../npc/gmod_zs/special/npc_zs_zombine.sp | 354 +++++++++++++ .../translations/zombieriot.phrases.icons.txt | 5 + .../zombieriot.phrases.zombienames.txt | 26 +- 64 files changed, 4896 insertions(+), 566 deletions(-) create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_angryheadcrab.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_infected_tomislav_main.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/45/npc_zs_hmo.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_manhattan_parrot.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_random_poyo.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_soldier_giant_grave.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_soldier_minion_grave.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_headcrab.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_headcrabzombie.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zmain_poisonzombie.sp create mode 100644 addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_zombine.sp 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..5795ef1c98 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); @@ -933,7 +945,7 @@ void DasNaggenvatcherSpawnEnemy(int dasnaggenvatcher, char[] plugin_name, int he } else { - int postWaves = CurrentRound[Rounds_Default] - Waves_GetMaxRound(); + int postWaves = CurrentRound - Waves_GetMaxRound(); char npc_classname[60]; NPC_GetPluginById(i_NpcInternalId[enemy.Index], npc_classname, sizeof(npc_classname)); @@ -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" From 6d42ced02f668969109ca889de285e43a69d8c72 Mon Sep 17 00:00:00 2001 From: Klajsdop Date: Tue, 10 Feb 2026 12:21:42 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EB=8B=A4=EC=8A=A4=20=EA=B3=A0=EB=A5=B4?= =?UTF-8?q?=ED=86=B5=EB=B3=B4=ED=98=B8=EA=B8=B0=20=EB=A9=94=EB=94=95?= =?UTF-8?q?=EC=9D=98=20=EC=BB=B4=ED=8C=8C=EC=9D=BC=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=9D=B4=EC=8A=88=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zombie_riot/npc/gmod_zs/bosses/npc_doctor_unclean_one.sp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5795ef1c98..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 @@ -945,7 +945,7 @@ void DasNaggenvatcherSpawnEnemy(int dasnaggenvatcher, char[] plugin_name, int he } else { - int postWaves = CurrentRound - Waves_GetMaxRound(); + int postWaves = CurrentRound[Rounds_Default] - Waves_GetMaxRound(); char npc_classname[60]; NPC_GetPluginById(i_NpcInternalId[enemy.Index], npc_classname, sizeof(npc_classname));