diff --git a/addons/sourcemod/configs/zombie_riot/fast_zs.cfg b/addons/sourcemod/configs/zombie_riot/fast_zs.cfg index 39f062d8ed..ed86dc6143 100644 --- a/addons/sourcemod/configs/zombie_riot/fast_zs.cfg +++ b/addons/sourcemod/configs/zombie_riot/fast_zs.cfg @@ -364,7 +364,7 @@ "grigori_sells_items_max" "3" "1.0" { - "count" "1" + "count" "0" "health" "45000" "is_boss" "1" "extra_damage" "1.25" diff --git a/addons/sourcemod/scripting/zombie_riot/npc.sp b/addons/sourcemod/scripting/zombie_riot/npc.sp index 63af4a737b..abfda090e2 100644 --- a/addons/sourcemod/scripting/zombie_riot/npc.sp +++ b/addons/sourcemod/scripting/zombie_riot/npc.sp @@ -2790,7 +2790,6 @@ Action NpcSpecificOnTakeDamage(int victim, int &attacker, int &inflictor, float #include "npc/gmod_zs/60/npc_zs_zombie_fatspy.sp" #include "npc/gmod_zs/60/npc_zs_medic_main.sp" #include "npc/gmod_zs/60/npc_zs_zombie_fatscout.sp" -#include "npc/gmod_zs/60/npc_zs_combine_soldier_elite.sp" #include "npc/gmod_zs/60/npc_zs_cleaner.sp" #include "npc/gmod_zs/60/npc_zs_vile_poisonheadcrab_zombie.sp" #include "npc/gmod_zs/60/npc_zs_stranger.sp" @@ -2802,6 +2801,7 @@ Action NpcSpecificOnTakeDamage(int victim, int &attacker, int &inflictor, float #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/bandit/npc_zs_combine_soldier_elite.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" 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 1266c014fa..66f2af4a2d 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 @@ -228,7 +228,16 @@ static void ZSoldierGrave_ClotThink(int iNPC) else { npc.StopPathing(); - npc.m_flGetClosestTargetTime = 0.0; + // 타겟이 사라졌으니 즉시 재탐색하도록 0.0으로 초기화 + npc.m_flGetClosestTargetTime = 0.0; + + // 추가: 멍청하게 서 있지 않도록 애니메이션 상태도 강제로 리셋 + if(npc.m_iChanged_WalkCycle != 1) + { + npc.m_iChanged_WalkCycle = 1; + npc.SetActivity("ACT_MP_STAND_PRIMARY"); + npc.m_flSpeed = 0.0; + } } npc.PlayIdleAlertSound(); } @@ -286,7 +295,7 @@ static int ZSoldierGrave_Work(ZSoldierGrave npc, float gameTime, int target, flo } // 위 조건들에 해당하지 않는 "애매한 거리"이거나 재장전 중일 때의 기본 행동 - return 1; // Stand / Attack Position + return 0; // 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/60/npc_zs_manhattan_parrot.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/60/npc_zs_manhattan_parrot.sp index 571c35431e..40dea72289 100644 --- 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 @@ -76,7 +76,7 @@ methodmap ManhattanParrot < CClotBody } 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)); + ManhattanParrot npc = view_as(CClotBody(vecPos, vecAng, "models/player/demo.mdl", "1.0", "30000", ally)); i_NpcWeight[npc.index] = 1; 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 1c79fb1558..f1690690d4 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 @@ -440,7 +440,7 @@ static void Spawn_Reinforcements(InfectedMessenger npc) SetEntProp(spawn_index, Prop_Data, "m_iHealth", maxhealth); SetEntProp(spawn_index, Prop_Data, "m_iMaxHealth", maxhealth); } - spawn_index = NPC_CreateByName("npc_zs_sniper", npc.index, pos, ang, GetTeam(npc.index)); + spawn_index = NPC_CreateByName("npc_zs_mlsm", npc.index, pos, ang, GetTeam(npc.index)); NpcAddedToZombiesLeftCurrently(spawn_index, true); if(spawn_index > MaxClients) { diff --git a/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bandit/npc_zs_combine_soldier_elite.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bandit/npc_zs_combine_soldier_elite.sp new file mode 100644 index 0000000000..95a96e347d --- /dev/null +++ b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/bandit/npc_zs_combine_soldier_elite.sp @@ -0,0 +1,494 @@ +#pragma semicolon 1 +#pragma newdecls required + +static const char g_DeathSounds[][] = { + "npc/combine_soldier/die1.wav", + "npc/combine_soldier/die2.wav", + "npc/combine_soldier/die3.wav", +}; + +static const char g_HurtSounds[][] = { + "npc/combine_soldier/pain1.wav", + "npc/combine_soldier/pain2.wav", + "npc/combine_soldier/pain3.wav", +}; + +static const char g_IdleSounds[][] = { + "npc/combine_soldier/vo/alert1.wav", + "npc/combine_soldier/vo/bouncerbouncer.wav", + "npc/combine_soldier/vo/boomer.wav", + "npc/combine_soldier/vo/contactconfim.wav", +}; + +static const char g_IdleAlertedSounds[][] = { + "npc/combine_soldier/vo/alert1.wav", + "npc/combine_soldier/vo/bouncerbouncer.wav", + "npc/combine_soldier/vo/boomer.wav", + "npc/combine_soldier/vo/contactconfim.wav", +}; + +static const char g_MeleeHitSounds[][] = { + "npc/vort/foot_hit.wav", +}; + +static const char g_MeleeAttackSounds[][] = { + "npc/combine_soldier/gear1.wav", + "npc/combine_soldier/gear2.wav", + "npc/combine_soldier/gear3.wav", + "npc/combine_soldier/gear4.wav", + "npc/combine_soldier/gear5.wav", + "npc/combine_soldier/gear6.wav", +}; + + +static const char g_RangedAttackSounds[][] = { + "weapons/ar2/fire1.wav", +}; + +static const char g_RangedAttackSoundsSecondary[][] = { + "weapons/irifle/irifle_fire2.wav", +}; + +static const char g_RangedReloadSound[][] = { + "weapons/ar2/npc_ar2_reload.wav", +}; + +void ZSCombineElite_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_DefaultMeleeMissSounds)); i++) { PrecacheSound(g_DefaultMeleeMissSounds[i]); } + for (int i = 0; i < (sizeof(g_RangedAttackSounds)); i++) { PrecacheSound(g_RangedAttackSounds[i]); } + for (int i = 0; i < (sizeof(g_RangedReloadSound)); i++) { PrecacheSound(g_RangedReloadSound[i]); } + for (int i = 0; i < (sizeof(g_RangedAttackSoundsSecondary)); i++) { PrecacheSound(g_RangedAttackSoundsSecondary[i]); } + PrecacheModel("models/combine_super_soldier.mdl"); + PrecacheModel("models/effects/combineball.mdl"); + NPCData data; + 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_GmodZS; + data.Func = ClotSummon; + NPC_Add(data); +} + +static any ClotSummon(int client, float vecPos[3], float vecAng[3], int team) +{ + return ZSCombineElite(vecPos, vecAng, team); +} +methodmap ZSCombineElite < 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() { + + EmitSoundToAll(g_HurtSounds[GetRandomInt(0, sizeof(g_HurtSounds) - 1)], this.index, SNDCHAN_VOICE, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + this.m_flNextHurtSound = GetGameTime(this.index) + GetRandomFloat(0.6, 1.6); + + + } + + 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, _, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + + public void PlayRangedSound() { + EmitSoundToAll(g_RangedAttackSounds[GetRandomInt(0, sizeof(g_RangedAttackSounds) - 1)], this.index, _, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + public void PlayRangedReloadSound() { + EmitSoundToAll(g_RangedReloadSound[GetRandomInt(0, sizeof(g_RangedReloadSound) - 1)], this.index, _, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + public void PlayRangedAttackSecondarySound() { + EmitSoundToAll(g_RangedAttackSoundsSecondary[GetRandomInt(0, sizeof(g_RangedAttackSoundsSecondary) - 1)], this.index, _, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + + public void PlayMeleeHitSound() { + EmitSoundToAll(g_MeleeHitSounds[GetRandomInt(0, sizeof(g_MeleeHitSounds) - 1)], this.index, _, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + + public void PlayMeleeMissSound() { + EmitSoundToAll(g_DefaultMeleeMissSounds[GetRandomInt(0, sizeof(g_DefaultMeleeMissSounds) - 1)], this.index, _, NORMAL_ZOMBIE_SOUNDLEVEL, _, NORMAL_ZOMBIE_VOLUME, 80); + + + } + + + public ZSCombineElite(float vecPos[3], float vecAng[3], int 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; + + FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); + + int iActivity = npc.LookupActivity("ACT_IDLE"); + if(iActivity > 0) npc.StartActivity(iActivity); + + npc.m_iBleedType = BLEEDTYPE_NORMAL; + npc.m_iStepNoiseType = STEPSOUND_NORMAL; + npc.m_iNpcStepVariation = STEPTYPE_COMBINE; + + 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 = 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; + + npc.m_iWearable1 = npc.EquipItem("anim_attachment_RH", "models/weapons/w_irifle.mdl"); + SetVariantString("1.15"); + AcceptEntityInput(npc.m_iWearable1, "SetModelScale"); + npc.StartPathing(); + + return npc; + } + +} + + +public void ZSCombineElite_ClotThink(int iNPC) +{ + ZSCombineElite npc = view_as(iNPC); + + // 1. 기본 지연 및 업데이트 + if(npc.m_flNextDelayTime > GetGameTime(npc.index)) return; + npc.m_flNextDelayTime = GetGameTime(npc.index) + DEFAULT_UPDATE_DELAY_FLOAT; + npc.Update(); + + // 2. 부상 애니메이션 + if(npc.m_blPlayHurtAnimation) + { + npc.AddGesture("ACT_GESTURE_FLINCH_STOMACH", false); + npc.m_blPlayHurtAnimation = false; + npc.PlayHurtSound(); + } + + // 3. AI 판단 지연 (0.1초) + if(npc.m_flNextThinkTime > GetGameTime(npc.index)) return; + npc.m_flNextThinkTime = GetGameTime(npc.index) + 0.1; + + // 4. 타겟팅 + 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); + + // --- 거리 기준 정의 --- + bool bInMeleeRange = (flDistanceToTarget < NORMAL_ENEMY_MELEE_RANGE_FLOAT_SQUARED); + bool bInRetreatRange = (flDistanceToTarget < 62500.0); // 약 250 unit + bool bInShootRange = (flDistanceToTarget < 122500.0); // 약 350 unit + bool bIsReloading = (npc.m_flReloadDelay > GetGameTime(npc.index)); + + // --- A. 이동 및 애니메이션 상태 제어 --- + if (bIsReloading) + { + npc.m_flSpeed = 0.0; + npc.StopPathing(); + // 재장전 애니메이션은 공격 로직에서 Gesture로 처리되므로 별도 Activity 불필요 + } + else if (bInMeleeRange) + { + // 근접 추격 모드 + npc.m_flSpeed = 330.0; + npc.StartPathing(); + npc.SetGoalEntity(PrimaryThreatIndex); + npc.m_fbGunout = false; + + if (npc.m_bmovedelay) // 상태가 바뀔 때만 애니메이션 재생 + { + int act = npc.LookupActivity("ACT_RUN_AIM_RIFLE"); + if(act > 0) npc.StartActivity(act); + npc.m_bmovedelay = false; + } + } + else if (bInRetreatRange) + { + // 후퇴(Kiting) 모드 + npc.m_flSpeed = 160.0; // 후퇴는 자연스럽게 속도 하향 + float vRetreatPos[3], vDir[3]; + MakeVectorFromPoints(vecTarget, VecSelfNpc, vDir); + NormalizeVector(vDir, vDir); + ScaleVector(vDir, 250.0); + AddVectors(VecSelfNpc, vDir, vRetreatPos); + + npc.SetGoalVector(vRetreatPos); + npc.StartPathing(); + npc.m_fbGunout = true; + + if (npc.m_bmovedelay) + { + int act = npc.LookupActivity("ACT_RUN_AIM_RIFLE"); + if(act > 0) npc.StartActivity(act); + npc.m_bmovedelay = false; + } + } + else if (bInShootRange) + { + // 제자리 사격 모드 + npc.m_flSpeed = 0.0; + npc.StopPathing(); + npc.m_fbGunout = true; + + if (!npc.m_bmovedelay) + { + int act = npc.LookupActivity("ACT_IDLE_ANGRY"); + if(act > 0) npc.StartActivity(act); + npc.m_bmovedelay = true; + } + } + else + { + // 원거리 추격 모드 + npc.m_flSpeed = 330.0; + npc.StartPathing(); + npc.SetGoalEntity(PrimaryThreatIndex); + npc.m_fbGunout = false; + + if (npc.m_bmovedelay) + { + int act = npc.LookupActivity("ACT_RUN_AIM_RIFLE"); + if(act > 0) npc.StartActivity(act); + npc.m_bmovedelay = false; + } + } + + // --- B. 공격 실행 로직 --- + if (!bIsReloading) + { + // 1. 근접 공격 + if(bInMeleeRange || npc.m_flAttackHappenswillhappen) + { + if (!npc.m_flAttackHappenswillhappen) + { + npc.AddGesture("ACT_MELEE_ATTACK1"); + 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)) + { + Handle swingTrace; + npc.FaceTowards(vecTarget, 20000.0); + if(npc.DoSwingTrace(swingTrace, PrimaryThreatIndex)) + { + int target = TR_GetEntityIndex(swingTrace); + if(target > 0) + { + SDKHooks_TakeDamage(target, npc.index, npc.index, 200.0, DMG_CLUB, -1, _, vecTarget); + Custom_Knockback(npc.index, target, 250.0); + npc.PlayMeleeHitSound(); + } + } + 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 = false; + } + } + // 2. 원거리 사격 (총을 꺼낸 상태일 때만) + else if (npc.m_fbGunout) + { + npc.FaceTowards(vecTarget, 10000.0); + + // 특수 공격 (로켓) + if(npc.m_flNextRangedSpecialAttack < GetGameTime(npc.index)) + { + float vPredictedPos[3]; PredictSubjectPosition(npc, PrimaryThreatIndex,_,_, vPredictedPos); + 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(); + } + + // 일반 사격 + if(npc.m_flNextRangedAttack < GetGameTime(npc.index) && Can_I_See_Enemy(npc.index, PrimaryThreatIndex) > 0) + { + npc.m_flNextRangedAttack = GetGameTime(npc.index) + 0.15; + npc.m_iAttacksTillReload -= 1; + + if (npc.m_iAttacksTillReload <= 0) + { + npc.AddGesture("ACT_RELOAD"); + npc.m_flReloadDelay = GetGameTime(npc.index) + 2.2; + npc.m_iAttacksTillReload = 30; + npc.PlayRangedReloadSound(); + } + else + { + npc.AddGesture("ACT_GESTURE_RANGE_ATTACK_AR2"); + // 사격 탄퍼짐 및 발사 로직 + float x = GetRandomFloat(-0.15, 0.15) + GetRandomFloat(-0.15, 0.15); + float y = GetRandomFloat(-0.15, 0.15) + GetRandomFloat(-0.15, 0.15); + float vecDirShooting[3], vecRight[3], vecUp[3], vecDir[3], eyePitch[3], SelfVecPos[3]; + + GetEntPropVector(npc.index, Prop_Data, "m_angRotation", eyePitch); + WorldSpaceCenter(npc.index, SelfVecPos); + vecTarget[2] += 15.0; + MakeVectorFromPoints(SelfVecPos, vecTarget, vecDirShooting); + GetVectorAngles(vecDirShooting, vecDirShooting); + vecDirShooting[1] = eyePitch[1]; + GetAngleVectors(vecDirShooting, vecDirShooting, vecRight, vecUp); + + vecDir[0] = vecDirShooting[0] + x * 0.1 * vecRight[0] + y * 0.1 * vecUp[0]; + vecDir[1] = vecDirShooting[1] + x * 0.1 * vecRight[1] + y * 0.1 * vecUp[1]; + 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, 30.0, 9000.0, DMG_BULLET, "bullet_tracer01_red"); + npc.PlayRangedSound(); + } + } + } + } + } + else + { + npc.StopPathing(); + npc.m_flGetClosestTargetTime = 0.0; + npc.m_iTarget = GetClosestTarget(npc.index); + } + npc.PlayIdleAlertSound(); +} + + +public Action ZSCombineElite_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; + + ZSCombineElite 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; +} + +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); + if(!npc.m_bGib) + { + npc.PlayDeathSound(); + } + + if(IsValidEntity(npc.m_iWearable1)) + RemoveEntity(npc.m_iWearable1); +} \ No newline at end of file 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 bc2593ec6a..8bf1838051 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 @@ -827,7 +827,7 @@ 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; + RaidModeTime += 15.0; 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)); @@ -839,13 +839,14 @@ public void DasNaggenvatcher_OnTakeDamagePost(int victim, int attacker, int infl 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); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_nightmare", RoundToCeil(100000.0 * MultiGlobalHighHealthBoss), 1); } else if(Ratio <= 0.55 && npc.g_TimesSummoned < 2) { npc.g_TimesSummoned = 2; npc.PlaySummonSound(); npc.m_flDoingSpecial = GetGameTime(npc.index) + 10.0; - RaidModeTime += 30.0; + RaidModeTime += 15.0; DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_eradicator",70000, RoundToCeil(6.0 * MultiGlobalEnemy)); DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_vile_poisonheadcrab_zombie",80000, RoundToCeil(6.0 * MultiGlobalEnemy)); @@ -854,13 +855,14 @@ public void DasNaggenvatcher_OnTakeDamagePost(int victim, int attacker, int infl 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); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_pregnant", RoundToCeil(100000.0 * MultiGlobalHighHealthBoss), 1); } else if(Ratio <= 0.35 && npc.g_TimesSummoned < 3) { npc.g_TimesSummoned = 3; npc.PlaySummonSound(); npc.m_flDoingSpecial = GetGameTime(npc.index) + 10.0; - RaidModeTime += 30.0; + RaidModeTime += 15.0; DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_ihbc",45000, RoundToCeil(5.0 * MultiGlobalEnemy)); DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_firefighter",50000, RoundToCeil(5.0 * MultiGlobalEnemy)); @@ -870,7 +872,8 @@ public void DasNaggenvatcher_OnTakeDamagePost(int victim, int attacker, int infl DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_sniper",20000, 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); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_malfunctioning_heavy", RoundToCeil(150000.0 * MultiGlobalHighHealthBoss), 1); + DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_sphynx", RoundToCeil(150000.0 * MultiGlobalHighHealthBoss), 1); } else if(Ratio <= 0.20 && npc.g_TimesSummoned < 4) { @@ -878,7 +881,7 @@ public void DasNaggenvatcher_OnTakeDamagePost(int victim, int attacker, int infl DasNaggenvatcherSayWords(npc.index); npc.g_TimesSummoned = 4; npc.PlaySummonSound(); - RaidModeTime += 30.0; + RaidModeTime += 15.0; npc.m_flDoingSpecial = GetGameTime(npc.index) + 10.0; DasNaggenvatcherSpawnEnemy(npc.index,"npc_zs_sniper",20000, RoundToCeil(2.0 * MultiGlobalEnemy)); 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 e55e7480a9..f509d810cd 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 @@ -650,7 +650,7 @@ public void ZsUnspeakable_ClotThink(int iNPC) // ForcePlayerLoss(); // RaidBossActive = INVALID_ENT_REFERENCE; // func_NPCThink[npc.index] = INVALID_FUNCTION; - CPrintToChatAll("{crimson}불결한 존재{crimson}: 전부 죽는다."); + CPrintToChatAll("{crimson}불결한 존재{crimson}: 오랫동안 기다려온 순간이 마침내 도래하였다."); SetEntPropFloat(npc.index, Prop_Send, "m_flModelScale", 1.85); RaidModeScaling *= 5.0; fl_Extra_Speed[npc.index] *= 1.2; @@ -799,16 +799,14 @@ public Action ZsUnspeakable_OnTakeDamage(int victim, int &attacker, int &inflict if(i_RaidGrantExtra[npc.index] >= 4) { SensalGiveShield(npc.index, CountPlayersOnRed(1) * 24); + if(!npc.m_bAlliesSummoned) + { + npc.m_bAlliesSummoned = true; + Spawn_Zombie(npc); + } + CPrintToChatAll("{crimson}불결한 존재{default}: 이 불경한 놈들이 감히!"); + RaidModeScaling *= 1.1; } - else - SensalGiveShield(npc.index, CountPlayersOnRed(1) * 12); - if(!npc.m_bAlliesSummoned) - { - npc.m_bAlliesSummoned = true; - Spawn_Zombie(npc); - } - CPrintToChatAll("{crimson}불결한 존재{default}: 이 불경한 놈들이 감히!"); - RaidModeScaling *= 1.1; } if(npc.g_TimesSummoned < 3) { 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 8158b4975f..6cd29831c7 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 @@ -21,13 +21,16 @@ static const char g_IdleAlertedSounds[][] = { "vo/taunts/heavy_taunts18.mp3", "vo/taunts/heavy_taunts19.mp3", }; - +static const char g_SelfRevive[][] = { + "mvm/mvm_bought_in.wav", +}; void Allyheavy_OnMapStart_NPC() { for (int i = 0; i < (sizeof(g_DeathSounds)); i++) { PrecacheSound(g_DeathSounds[i]); } for (int i = 0; i < (sizeof(g_HurtSounds)); i++) { PrecacheSound(g_HurtSounds[i]); } for (int i = 0; i < (sizeof(g_IdleAlertedSounds)); i++) { PrecacheSound(g_IdleAlertedSounds[i]); } + for (int i = 0; i < (sizeof(g_SelfRevive)); i++) { PrecacheSound(g_SelfRevive[i]); } PrecacheModel("models/player/heavy.mdl"); PrecacheSound("weapons/minigun_spin.wav"); PrecacheSound("weapons/minigun_shoot.wav"); @@ -102,10 +105,24 @@ methodmap Allyheavy < CClotBody this.i_GunMode = 1; } } + public void PlaySelfRevive() + { + EmitSoundToAll(g_SelfRevive[GetRandomInt(0, sizeof(g_SelfRevive) - 1)], this.index, SNDCHAN_STATIC, BOSS_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME, 60); + } + property float m_flSelfRevival + { + public get() { return fl_AbilityOrAttack[this.index][6]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][6] = TempValueForProperty; } + } + property float m_flWasIdleState + { + public get() { return fl_AbilityOrAttack[this.index][7]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][7] = TempValueForProperty; } + } public Allyheavy(float vecPos[3], float vecAng[3], int ally) { - Allyheavy npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "300", ally, true, false)); + Allyheavy npc = view_as(CClotBody(vecPos, vecAng, "models/player/heavy.mdl", "1.0", "3000", ally, false, true)); i_NpcWeight[npc.index] = 1; FormatEx(c_HeadPlaceAttachmentGibName[npc.index], sizeof(c_HeadPlaceAttachmentGibName[]), "head"); @@ -124,11 +141,14 @@ methodmap Allyheavy < CClotBody SetEntPropFloat(npc.index, Prop_Data, "m_flElementRes", 1.0, Element_Chaos); npc.StartPathing(); - npc.m_flSpeed = 230.0; - npc.m_bThisEntityIgnored = true; - b_NpcIsInvulnerable[npc.index] = true; + npc.m_flSpeed = 330.0; npc.m_bScalesWithWaves = false; + npc.m_iTeamGlow = TF2_CreateGlow(npc.index); + npc.m_bTeamGlowDefault = false; + SetVariantColor(view_as({255, 0, 0, 0})); + AcceptEntityInput(npc.m_iTeamGlow, "SetGlowColor"); + int skin = 0; SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); @@ -142,20 +162,9 @@ 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) - { - SetEntityRenderMode(npc.index, RENDER_TRANSCOLOR); - SetEntityRenderColor(npc.index, 255, 255, 255, 125); - SetEntityRenderMode(npc.m_iWearable1, RENDER_TRANSCOLOR); - SetEntityRenderColor(npc.m_iWearable1, 255, 255, 255, 125); - } + + b_ShowNpcHealthbar[npc.index] = true; SetEntProp(npc.m_iWearable1, Prop_Send, "m_nSkin", skin); return npc; @@ -200,6 +209,17 @@ public void Allyheavy_ClotThink(int iNPC) return; } npc.m_flNextThinkTime = gametime + 0.1; + if(!b_ShowNpcHealthbar[iNPC]) + { + if(npc.m_flSelfRevival && npc.m_flSelfRevival < GetGameTime()) + { + npc.PlaySelfRevive(); + DesertYadeamDoHealEffect(iNPC, 200.0); + SetDownedState_Allyheavy(iNPC, false); + } + //stunned + return; + } int ally = npc.m_iTargetWalkTo; @@ -294,9 +314,83 @@ public Action Allyheavy_OnTakeDamage(int victim, int &attacker, int &inflictor, npc.m_blPlayHurtAnimation = true; } + if(RoundToNearest(damage) < GetEntProp(victim, Prop_Data, "m_iHealth")) + return Plugin_Changed; + + SetDownedState_Allyheavy(victim, true); + damage = 0.0; + //we died. return Plugin_Changed; } - +void SetDownedState_Allyheavy(int iNpc, bool StateDo) +{ + Allyheavy npc = view_as(iNpc); + if(StateDo) //downed + { + npc.m_flSelfRevival = GetGameTime() + 30.0; + b_ShowNpcHealthbar[iNpc] = false; + b_ThisEntityIgnored[iNpc] = true; + b_NpcIsInvulnerable[iNpc] = true; + SetEntProp(iNpc, Prop_Data, "m_iHealth", 1); + if(!npc.m_flWasIdleState) + { + npc.m_flWasIdleState = 1.0; + npc.StopPathing(); + npc.m_bisWalking = false; + npc.AddGesture("ACT_MP_STUN_BEGIN"); + npc.SetActivity("ACT_MP_STUN_MIDDLE"); + } + SetEntityRenderMode(npc.index, RENDER_TRANSALPHA); + if(IsValidEntity(npc.m_iWearable1)) + { + SetEntityRenderMode(npc.m_iWearable1, RENDER_TRANSALPHA); + } + if(IsValidEntity(npc.m_iWearable2)) + { + SetEntityRenderMode(npc.m_iWearable2, RENDER_TRANSALPHA); + } + if(IsValidEntity(npc.m_iWearable3)) + { + SetEntityRenderMode(npc.m_iWearable3, RENDER_TRANSALPHA); + } + if(IsValidEntity(npc.m_iWearable4)) + { + SetEntityRenderMode(npc.m_iWearable4, RENDER_TRANSALPHA); + } + } + else + { + if(npc.m_flWasIdleState) + { + npc.m_flWasIdleState = 0.0; + npc.SetActivity("ACT_MP_DEPLOYED_PRIMARY"); + npc.AddGesture("ACT_MP_ATTACK_STAND_PRIMARY", false); + } + npc.m_flSelfRevival = 0.0; + b_ShowNpcHealthbar[iNpc] = true; + b_ThisEntityIgnored[iNpc] = false; + b_NpcIsInvulnerable[iNpc] = false; + SetEntProp(iNpc, Prop_Data, "m_iHealth", ReturnEntityMaxHealth(iNpc)); + SetEntityRenderMode(npc.index, RENDER_NORMAL); + if(IsValidEntity(npc.m_iWearable1)) + { + SetEntityRenderMode(npc.m_iWearable1, RENDER_NORMAL); + } + if(IsValidEntity(npc.m_iWearable2)) + { + SetEntityRenderMode(npc.m_iWearable2, RENDER_NORMAL); + } + if(IsValidEntity(npc.m_iWearable3)) + { + SetEntityRenderMode(npc.m_iWearable3, RENDER_NORMAL); + } + if(IsValidEntity(npc.m_iWearable4)) + { + SetEntityRenderMode(npc.m_iWearable4, RENDER_NORMAL); + } + } + +} public void Allyheavy_NPCDeath(int entity) { Allyheavy npc = view_as(entity); 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 2d42c60082..f9514cc791 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 @@ -119,7 +119,7 @@ methodmap Allymedic < CClotBody npc.m_iTeamGlow = TF2_CreateGlow(npc.index); npc.m_bTeamGlowDefault = false; - SetVariantColor(view_as({255, 255, 255, 255})); + SetVariantColor(view_as({255, 0, 0, 0})); AcceptEntityInput(npc.m_iTeamGlow, "SetGlowColor"); int skin = 0; @@ -339,9 +339,11 @@ static int Medic_Work(Allymedic npc, float distance) else { npc.StopHealing(); - npc.m_bnew_target = false; + npc.m_bnew_target = false; + npc.SetGoalEntity(npc.m_iTargetWalkTo); + return 0; } - return 0; + //return 0; } npc.m_iTargetWalkTo=0; } 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 fe54a0fc29..c6956ff838 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 @@ -121,7 +121,7 @@ methodmap AllySniper < CClotBody npc.m_iTeamGlow = TF2_CreateGlow(npc.index); npc.m_bTeamGlowDefault = false; - SetVariantColor(view_as({255, 255, 255, 255})); + SetVariantColor(view_as({255, 0, 0, 0})); AcceptEntityInput(npc.m_iTeamGlow, "SetGlowColor"); if(npc.m_bScalesWithWaves) 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 9b0308f20c..12d82a4756 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 @@ -32,10 +32,16 @@ static const char g_IdleAlertedSounds[][] = { "vo/taunts/soldier_taunts18.mp3", }; +static const char g_SelfRevive[][] = { + "mvm/mvm_bought_in.wav", +}; + static const char g_RangeAttackSounds[] = "weapons/rocket_shoot.wav"; void Allysoldier_OnMapStart_NPC() { + for (int i = 0; i < (sizeof(g_SelfRevive)); i++) { PrecacheSound(g_SelfRevive[i]); } + NPCData data; strcopy(data.Name, sizeof(data.Name), "Freedom Feathers"); strcopy(data.Plugin, sizeof(data.Plugin), "npc_zs_ally_soldier"); @@ -93,10 +99,24 @@ methodmap Allysoldier < CClotBody public void PlayRangeSound() { EmitSoundToAll(g_RangeAttackSounds, this.index, SNDCHAN_STATIC, 80, _, NORMAL_ZOMBIE_VOLUME, GetRandomInt(NORMAL_ZOMBIE_SOUNDLEVEL, 100)); } + public void PlaySelfRevive() + { + EmitSoundToAll(g_SelfRevive[GetRandomInt(0, sizeof(g_SelfRevive) - 1)], this.index, SNDCHAN_STATIC, BOSS_ZOMBIE_SOUNDLEVEL, _, BOSS_ZOMBIE_VOLUME, 60); + } + property float m_flSelfRevival + { + public get() { return fl_AbilityOrAttack[this.index][6]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][6] = TempValueForProperty; } + } + property float m_flWasIdleState + { + public get() { return fl_AbilityOrAttack[this.index][7]; } + public set(float TempValueForProperty) { fl_AbilityOrAttack[this.index][7] = TempValueForProperty; } + } public Allysoldier(float vecPos[3], float vecAng[3], int ally) { - Allysoldier npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "200", ally, true, false)); + Allysoldier npc = view_as(CClotBody(vecPos, vecAng, "models/player/soldier.mdl", "1.0", "2000", ally, false, true)); i_NpcWeight[npc.index] = 1; @@ -119,9 +139,7 @@ methodmap Allysoldier < CClotBody func_NPCThink[npc.index] = Allysoldier_ClotThink; //IDLE - npc.m_bThisEntityIgnored = true; - b_NpcIsInvulnerable[npc.index] = true; - npc.m_flSpeed = 240.0; + npc.m_flSpeed = 330.0; npc.m_iMaxAmmo = 1; npc.m_iAmmo = 1; npc.m_bScalesWithWaves = false; @@ -131,7 +149,7 @@ methodmap Allysoldier < CClotBody npc.m_iTeamGlow = TF2_CreateGlow(npc.index); npc.m_bTeamGlowDefault = false; - SetVariantColor(view_as({255, 255, 255, 255})); + SetVariantColor(view_as({255, 0, 0, 0})); AcceptEntityInput(npc.m_iTeamGlow, "SetGlowColor"); int skin = 0; @@ -149,13 +167,7 @@ methodmap Allysoldier < CClotBody SetEntProp(npc.m_iWearable3, Prop_Send, "m_nSkin", 0); SetEntProp(npc.m_iWearable4, Prop_Send, "m_nSkin", 0); - if(npc.m_bScalesWithWaves) - { - SetEntityRenderMode(npc.index, RENDER_TRANSCOLOR); - SetEntityRenderColor(npc.index, 255, 255, 255, 125); - SetEntityRenderMode(npc.m_iWearable1, RENDER_TRANSCOLOR); - SetEntityRenderColor(npc.m_iWearable1, 255, 255, 255, 125); - } + b_ShowNpcHealthbar[npc.index] = true; return npc; } @@ -175,9 +187,21 @@ static void Allysoldier_ClotThink(int iNPC) npc.Update(); if(npc.m_flNextThinkTime > gametime) + { return; + } npc.m_flNextThinkTime = gametime + 0.1; - + if(!b_ShowNpcHealthbar[iNPC]) + { + if(npc.m_flSelfRevival && npc.m_flSelfRevival < GetGameTime()) + { + npc.PlaySelfRevive(); + DesertYadeamDoHealEffect(iNPC, 200.0); + SetDownedState_Allysoldier(iNPC, false); + } + //stunned + return; + } float VecSelfNpcabs[3]; GetEntPropVector(npc.index, Prop_Data, "m_vecAbsOrigin", VecSelfNpcabs); Allysoldier_ApplyBuffInLocation_Optimized(VecSelfNpcabs, GetTeam(npc.index), npc.index); @@ -216,7 +240,7 @@ static void Allysoldier_ClotThink(int iNPC) npc.m_bAllowBackWalking = false; npc.m_iChanged_WalkCycle = 0; npc.SetActivity("ACT_MP_RUN_PRIMARY"); - npc.m_flSpeed = 240.0; + npc.m_flSpeed = 330.0; npc.StartPathing(); } @@ -251,7 +275,7 @@ static void Allysoldier_ClotThink(int iNPC) npc.m_bAllowBackWalking = true; npc.m_iChanged_WalkCycle = 2; npc.SetActivity("ACT_MP_RUN_PRIMARY"); - npc.m_flSpeed = 240.0; + npc.m_flSpeed = 330.0; npc.StartPathing(); } float vBackoffPos[3]; @@ -272,7 +296,7 @@ static void Allysoldier_ClotThink(int iNPC) if(flDistanceToTarget > 40000.0) { npc.m_iChanged_WalkCycle = 0; - npc.m_flSpeed = 240.0; + npc.m_flSpeed = 330.0; npc.SetActivity("ACT_MP_RUN_PRIMARY"); npc.FaceTowards(vecTarget, 20000.0); npc.SetGoalEntity(ally); @@ -390,9 +414,82 @@ static Action Allysoldier_OnTakeDamage(int victim, int &attacker, int &inflictor npc.m_blPlayHurtAnimation = true; } + if(RoundToNearest(damage) < GetEntProp(victim, Prop_Data, "m_iHealth")) + return Plugin_Changed; + + SetDownedState_Allysoldier(victim, true); + damage = 0.0; + //we died. return Plugin_Changed; } - +void SetDownedState_Allysoldier(int iNpc, bool StateDo) +{ + Allysoldier npc = view_as(iNpc); + if(StateDo) //downed + { + npc.m_flSelfRevival = GetGameTime() + 30.0; + b_ShowNpcHealthbar[iNpc] = false; + b_ThisEntityIgnored[iNpc] = true; + b_NpcIsInvulnerable[iNpc] = true; + SetEntProp(iNpc, Prop_Data, "m_iHealth", 1); + if(!npc.m_flWasIdleState) + { + npc.m_flWasIdleState = 1.0; + npc.StopPathing(); + npc.m_bisWalking = false; + npc.AddGesture("ACT_MP_STUN_BEGIN"); + npc.SetActivity("ACT_MP_STUN_MIDDLE"); + } + SetEntityRenderMode(npc.index, RENDER_TRANSALPHA); + if(IsValidEntity(npc.m_iWearable1)) + { + SetEntityRenderMode(npc.m_iWearable1, RENDER_TRANSALPHA); + } + if(IsValidEntity(npc.m_iWearable2)) + { + SetEntityRenderMode(npc.m_iWearable2, RENDER_TRANSALPHA); + } + if(IsValidEntity(npc.m_iWearable3)) + { + SetEntityRenderMode(npc.m_iWearable3, RENDER_TRANSALPHA); + } + if(IsValidEntity(npc.m_iWearable4)) + { + SetEntityRenderMode(npc.m_iWearable4, RENDER_TRANSALPHA); + } + } + else + { + if(npc.m_flWasIdleState) + { + npc.m_flWasIdleState = 0.0; + npc.SetActivity("ACT_MP_RUN_PRIMARY"); + } + npc.m_flSelfRevival = 0.0; + b_ShowNpcHealthbar[iNpc] = true; + b_ThisEntityIgnored[iNpc] = false; + b_NpcIsInvulnerable[iNpc] = false; + SetEntProp(iNpc, Prop_Data, "m_iHealth", ReturnEntityMaxHealth(iNpc)); + SetEntityRenderMode(npc.index, RENDER_NORMAL); + if(IsValidEntity(npc.m_iWearable1)) + { + SetEntityRenderMode(npc.m_iWearable1, RENDER_NORMAL); + } + if(IsValidEntity(npc.m_iWearable2)) + { + SetEntityRenderMode(npc.m_iWearable2, RENDER_NORMAL); + } + if(IsValidEntity(npc.m_iWearable3)) + { + SetEntityRenderMode(npc.m_iWearable3, RENDER_NORMAL); + } + if(IsValidEntity(npc.m_iWearable4)) + { + SetEntityRenderMode(npc.m_iWearable4, RENDER_NORMAL); + } + } + +} static void Allysoldier_NPCDeath(int entity) { Allysoldier npc = view_as(entity); 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 23c4af302a..a915636ede 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 @@ -281,7 +281,6 @@ 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_malfunctioning_heavy.sp b/addons/sourcemod/scripting/zombie_riot/npc/gmod_zs/special/npc_zs_malfunctioning_heavy.sp index 194c63ec5c..1202bc379a 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 @@ -168,6 +168,22 @@ methodmap ZsMalfuncHeavy < CClotBody RaidModeScaling = 0.0; RaidAllowsBuildings = true; } + + switch(GetRandomInt(0,2)) + { + case 0: + { + CPrintToChatAll("{green}오버히터{default}: 놈들을 응징할 시간이다."); + } + case 1: + { + CPrintToChatAll("{green}오버히터{default}: 절망 속으로 가라앉아라."); + } + case 2: + { + CPrintToChatAll("{green}오버히터{default}: 네놈을 삼켜주마."); + } + } int skin = 5; SetEntProp(npc.index, Prop_Send, "m_nSkin", skin); @@ -239,7 +255,21 @@ public void ZsMalfuncHeavy_ClotThink(int iNPC) { if(npc.i_Hit >= 5) { - CPrintToChatAll("{green}오버히터{default}: {crimson}널 박살내주마."); + switch(GetRandomInt(0,2)) + { + case 0: + { + CPrintToChatAll("{green}오버히터{default}: 내 고통을 느껴라!"); + } + case 1: + { + CPrintToChatAll("{green}오버히터{default}: 어리석음의 대가를 치러라."); + } + case 2: + { + CPrintToChatAll("{green}오버히터{default}: 한순간의 착오로 모든 걸 잃게 되리라."); + } + } npc.PlayIdleSound(); npc.Anger = true; npc.i_Hit = 0; @@ -267,7 +297,17 @@ public void ZsMalfuncHeavy_ClotThink(int iNPC) } else { - CPrintToChatAll("{green}오버히터{default}: {default}이러고 있을 시간 없다."); + switch(GetRandomInt(0,1)) + { + case 0: + { + CPrintToChatAll("{green}오버히터{default}: 넌 아무것도 아니다!"); + } + case 1: + { + CPrintToChatAll("{green}오버히터{default}: 버러지들 같으니."); + } + } npc.Anger = false; npc.f_Overheat_Cooldown = 0.0; npc.f_Overheat_Timer = 0.0; @@ -405,6 +445,8 @@ static Action ZsMalfuncHeavy_OnTakeDamage(int victim, int &attacker, int &inflic static void ZsMalfuncHeavy_NPCDeath(int entity) { ZsMalfuncHeavy npc = view_as(entity); + + CPrintToChatAll("{green}오버히터{default}: 겨우 그까짓 힘으로 감히!"); if(IsValidEntity(npc.m_iWearable1)) RemoveEntity(npc.m_iWearable1);