mirror of
https://github.com/PhantomGamesDevelopment/TWM2.git
synced 2026-01-19 19:44:47 +00:00
Sniper Zombie, Bug Fixes
Upgraded the sniper zombie to the new AI system, fixed a few logic errors in the ZombieCore file.
This commit is contained in:
parent
0ad6bd6eba
commit
f5160868da
|
|
@ -99,6 +99,11 @@ PLEASE NOTE: I've moved all old changelogs into the version_history folder. This
|
|||
* Increased the maximum targeting range of the teleport attack from 200m to 400m
|
||||
* Increased the cooldown of the teleport attack from 7 seconds to 12.5 seconds
|
||||
* Shifter zombies will now have to "lock down" for a 1.5 seconds before teleporting, during this time they will be easily targetable
|
||||
* Sniper
|
||||
* The sniper zombie is now armed with two new weapons.
|
||||
* The first is an acid sniper rifle which infects players on striking
|
||||
* The second is a rapid fire sidearm that the sniper will use when targets move too close
|
||||
* Reduced the health of Sniper Zombies from 40 (4.0) to 25 (2.5)
|
||||
* Added Boss Proficiency
|
||||
* Hidden challenges embedded in boss fights that award additional experience for completing tough feats
|
||||
* For example: Defeat the shade lord without dying by the elemental shades
|
||||
|
|
|
|||
|
|
@ -513,6 +513,7 @@ $ZArmor[1, 2] = "Rav\t0\tRavenger Zombie\tAbility: Jet Key To Speed Forward/Lung
|
|||
$ZArmor[2, 2] = "Lord\t0\tZombie Lord\tAbilities: Jet Key To Fire, Mine Key To Lift";
|
||||
$ZArmor[3, 2] = "Demon\t0\tDemon Zombie\tAbility: Jet Key To Throw Fireball";
|
||||
$ZArmor[4, 2] = "Rap\t1\tAir Rapier Zombie\tAbility: Jet Key Flies";
|
||||
$ZArmor[5, 2] = "VolRav\t1\tVolatile Ravenger Zombie\tAbility: Jet Key To Detonate C4";
|
||||
|
||||
$ZArmor[0, 3] = "Norm\t0\tNormal Zombie\tAbility: Jet Key To Lunge";
|
||||
$ZArmor[1, 3] = "Rav\t0\tRavenger Zombie\tAbility: Jet Key To Speed Forward/Lunge";
|
||||
|
|
@ -521,7 +522,7 @@ $ZArmor[3, 3] = "Demon\t0\tDemon Zombie\tAbility: Jet Key To Throw Fireball";
|
|||
$ZArmor[4, 3] = "Rap\t0\tAir Rapier Zombie\tAbility: Jet Key Flies";
|
||||
$ZArmor[5, 3] = "VolRav\t0\tVolatile Ravenger Zombie\tAbility: Jet Key To Detonate C4";
|
||||
$ZArmor[6, 3] = "UDem\t1\tUltra Demon Zombie\tAbility: Jet Key To Fire, Mine To Charge Forward";
|
||||
$ZArmor[7, 3] = "Wraith\t1\tWraith Spec-Ops Zombie\tAbility: Jet Key To Charge, Armed with MP26-CMDO";
|
||||
//$ZArmor[7, 3] = "Wraith\t1\tWraith Spec-Ops Zombie\tAbility: Jet Key To Charge, Armed with MP26-CMDO";
|
||||
|
||||
$ZArmor[0, 4] = "Norm\t0\tNormal Zombie\tAbility: Jet Key To Lunge";
|
||||
$ZArmor[1, 4] = "Rav\t0\tRavenger Zombie\tAbility: Jet Key To Speed Forward/Lunge";
|
||||
|
|
@ -530,8 +531,8 @@ $ZArmor[3, 4] = "Demon\t0\tDemon Zombie\tAbility: Jet Key To Throw Fireball";
|
|||
$ZArmor[4, 4] = "Rap\t0\tAir Rapier Zombie\tAbility: Jet Key Flies";
|
||||
$ZArmor[5, 4] = "VolRav\t0\tVolatile Ravenger Zombie\tAbility: Jet Key To Detonate C4";
|
||||
$ZArmor[6, 4] = "UDem\t0\tUltra Demon Zombie\tAbility: Jet Key To Fire, Mine To Charge Forward";
|
||||
$ZArmor[7, 4] = "Wraith\t0\tWraith Spec-Ops Zombie\tAbility: Jet Key To Charge, Armed with MP26-CMDO";
|
||||
$ZArmor[8, 4] = "Rog\t1\tGeneral Rog\tAbilities: Jet Key To fire zMG42, Shielded, Armed with BoV";
|
||||
//$ZArmor[7, 4] = "Flareguide\t0\tFist of Vengeance Flareguide\tAbility: Armed with the Bursting NLS-22 Rifle, Grenade to Vanish";
|
||||
//$ZArmor[8, 4] = "Rog\t1\tGeneral Rog\tAbilities: Jet Key To fire zMG42, Shielded, Armed with BoV";
|
||||
|
||||
//Score Hud
|
||||
$ScoreHudMaxVisible = 19;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,24 @@
|
|||
//**********************************************
|
||||
//**********************************************
|
||||
// Player Zombie Functioning
|
||||
//
|
||||
// Updated TWM2 3.9.2
|
||||
// Cleaned up all of the functions and converted it into a library style
|
||||
// system to reduce the function count
|
||||
//**********************************************
|
||||
//**********************************************
|
||||
|
||||
function TWM2Lib_Zombie_PlayerFunctions(%functionName, %arg1, %arg2, %arg3, %arg4) {
|
||||
switch$(strlwr(%functionName)) {
|
||||
case "zombieattackimpulse":
|
||||
|
||||
case "makepersonzombie":
|
||||
|
||||
default:
|
||||
error("TWM2Lib_Zombie_PlayerFunctions(): Unknown function name "@%functionName@" sent to call.");
|
||||
}
|
||||
}
|
||||
|
||||
function makePersonHumanFZomb(%trans, %client){
|
||||
%client.player.delete();
|
||||
%player = new Player() {
|
||||
|
|
|
|||
|
|
@ -105,6 +105,22 @@ $Zombie::Shifter_Teleport_Cooldown = 12500;
|
|||
//$Zombie::Summoner_Cooldown: The cooldown of the summoner zombie's summon ability
|
||||
$Zombie::Summoner_Cooldown = 25000;
|
||||
|
||||
//$Zombie::Sniper_MaximumEngageRange: The maximum range at which the sniper zombie will fire at.
|
||||
// NOTE: If the target is outside of this range, the sniper will begin "consideration" to look for a new target
|
||||
$Zombie::Sniper_MaximumEngageRange = 450;
|
||||
//$Zombie::Sniper_PreferedDistanceFromTarget: The range at which the sniper zombie will move up to try to reach
|
||||
$Zombie::Sniper_PreferedDistanceFromTarget = 300;
|
||||
//$Zombie::Sniper_SidearmRange: The range at which the sniper zombie engages CQC combat with it's sidearm
|
||||
$Zombie::Sniper_SidearmRange = 50;
|
||||
//$Zombie::Sniper_RifleCooldown: The reload time of the sniper zombie's rifle (MS)
|
||||
$Zombie::Sniper_RifleCooldown = 7000;
|
||||
//$Zombie::Sniper_SidearmBurstCount: The amount of shots in a sidearm burst
|
||||
$Zombie::Sniper_SidearmBurstCount = 10;
|
||||
//$Zombie::Sniper_SidearmBurstTime: The amount of time to fire off the full burst
|
||||
$Zombie::Sniper_SidearmBurstTime = 600;
|
||||
//$Zombie::Sniper_SidearmCooldown: The reload time of the sniper zombie's sidearm (MS)
|
||||
$Zombie::Sniper_SidearmCooldown = 5000;
|
||||
|
||||
//MISC Globals, Do not edit.
|
||||
$Zombie::killpoints = 5;
|
||||
$Zombie::RogThread = "cel1";
|
||||
|
|
@ -173,7 +189,7 @@ function TWM2Lib_Zombie_Core(%functionName, %arg1, %arg2, %arg3, %arg4) {
|
|||
%vec = %rx @ " " @ %ry @ " " @ 0;
|
||||
%arg1.direction = vectorNormalize(%vec);
|
||||
%arg1.Mnum = getRandom(1, 20);
|
||||
%arg1.zombieRmove = schedule($Zombie::SpeedUpdateTime, %arg1, "TWM2Lib_Zombie_Core", "zRandomMoveLoop", %arg1);
|
||||
%arg1.zombieRmove = schedule(%arg1.updateTimeFrequency, %arg1, "TWM2Lib_Zombie_Core", "zRandomMoveLoop", %arg1);
|
||||
|
||||
//zrandommoveloop(%zombie): Moves the zombies around in a random direction
|
||||
case "zrandommoveloop":
|
||||
|
|
@ -193,10 +209,10 @@ function TWM2Lib_Zombie_Core(%functionName, %arg1, %arg2, %arg3, %arg4) {
|
|||
%vector = vectorScale(%vec, %speed);
|
||||
%arg1.applyImpulse(%arg1.direction, %vector);
|
||||
%arg1.Mnum -= 1;
|
||||
%arg1.zombieRmove = schedule($Zombie::SpeedUpdateTime, %arg1, "TWM2Lib_Zombie_Core", "zRandomMoveLoop", %arg1);
|
||||
%arg1.zombieRmove = schedule(%arg1.updateTimeFrequency, %arg1, "TWM2Lib_Zombie_Core", "zRandomMoveLoop", %arg1);
|
||||
}
|
||||
else {
|
||||
%arg1.zombieRmove = schedule($Zombie::SpeedUpdateTime, %arg1, "TWM2Lib_Zombie_Core", "zRandomMoveLoop", %arg1);
|
||||
%arg1.zombieRmove = schedule(%arg1.updateTimeFrequency, %arg1, "TWM2Lib_Zombie_Core", "zRandomMoveLoop", %arg1);
|
||||
}
|
||||
|
||||
//cureInfection(%player): Cures the zombie infection
|
||||
|
|
@ -304,6 +320,8 @@ function TWM2Lib_Zombie_Core(%functionName, %arg1, %arg2, %arg3, %arg4) {
|
|||
%arg1.firingWeapon = %arg3;
|
||||
case "canfireweapon":
|
||||
%arg1.canFireWeapon = %arg3;
|
||||
case "canaltfire":
|
||||
%arg1.canAltFire = %arg3;
|
||||
}
|
||||
|
||||
//lookForTarget(%zombie, [%pilot], [%groundVeh]): Identify the closest target, and the distance to that target
|
||||
|
|
@ -560,6 +578,8 @@ function TWM2Lib_Zombie_Core(%functionName, %arg1, %arg2, %arg3, %arg4) {
|
|||
%zombie.mountImage(ZSniperImage1, 4);
|
||||
%zombie.mountImage(ZSniperImage2, 5);
|
||||
%zombie.mountImage(ZSniperImage3, 6);
|
||||
%zombie.canFireWeapon = 1;
|
||||
%zombie.canAltFire = 1;
|
||||
|
||||
//Ultra-Demon Zombie
|
||||
case 12:
|
||||
|
|
@ -616,7 +636,7 @@ function TWM2Lib_Zombie_Core(%functionName, %arg1, %arg2, %arg3, %arg4) {
|
|||
%zombie.mountImage(ZdummyslotImg, 4);
|
||||
|
||||
//Flareguide Sniper Zombie (Mini-Boss)
|
||||
case 11:
|
||||
case 18:
|
||||
%zombie = new player(){
|
||||
Datablock = "FlareguideSniperZombieArmor";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,16 +63,52 @@ function SniperZombieArmor::AI(%datablock, %zombie) {
|
|||
return;
|
||||
}
|
||||
%pos = %zombie.getWorldBoxCenter();
|
||||
//Target update.
|
||||
if(%zombie.hadTarget) {
|
||||
if(!isObject(%zombie.targetPlayer) || %zombie.targetPlayer.getState() $= "dead") {
|
||||
//Target is down for the count, let's move on.
|
||||
%zombie.hasTarget = 0;
|
||||
%zombie.CQCTarget = 0;
|
||||
%zombie.reallyFarTarget = 0;
|
||||
%zombie.targetPlayer = 0;
|
||||
}
|
||||
}
|
||||
//Do I have a target, but it's far out (IE: Running or Pilot?)
|
||||
if(%zombie.hasTarget && %zombie.reallyFarTarget) {
|
||||
//Throw a 1 in 25 chance to abort and re-search
|
||||
if(getRandom(1, 25) == 19) {
|
||||
%zombie.hasTarget = 0;
|
||||
%zombie.targetPlayer = 0;
|
||||
%zombie.CQCTarget = 0;
|
||||
%zombie.reallyFarTarget = 0;
|
||||
}
|
||||
}
|
||||
//Are there any targets?
|
||||
if(!%zombie.hasTarget) {
|
||||
%preferSniper = getRandom(1, 10);
|
||||
if(%preferSniper > 3) {
|
||||
if(%preferSniper > 4) {
|
||||
for(%i = 0; %i < ClientGroup.getCount(%i); %i++) {
|
||||
%check = ClientGroup.getObject(%i);
|
||||
if(isObject(%check.player) && %check.player.getState() !$= "dead") {
|
||||
//Check their weapon
|
||||
|
||||
%w = %check.player.getMountedImage($WeaponSlot).getName();
|
||||
if(!strStr(strlwr(%w), "sniper")) {
|
||||
//Bingo!
|
||||
%zombie.hasTarget = 1;
|
||||
%zombie.targetPlayer = %check.player;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//No enemy snipers found... Look for a new target.
|
||||
if(!%zombie.hasTarget) {
|
||||
%closestClient = TWM2Lib_Zombie_Core("lookForTarget", %zombie);
|
||||
%closestDistance = getWord(%closestClient, 1);
|
||||
if(isObject(%closestClient.player) && %closestClient.player.getState() !$= "dead") {
|
||||
%zombie.hasTarget = 1;
|
||||
%zombie.targetPlayer = %closestClient.player;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
%closestClient = TWM2Lib_Zombie_Core("lookForTarget", %zombie);
|
||||
|
|
@ -83,8 +119,48 @@ function SniperZombieArmor::AI(%datablock, %zombie) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
%zombie.moveloop = %datablock.Move(%zombie);
|
||||
//Do I have a target?
|
||||
if(%zombie.hasTarget) {
|
||||
//Check the distance...
|
||||
%tPos = %zombie.targetPlayer.getPosition();
|
||||
%dist = vectorDist(%pos, %tPos);
|
||||
if(%dist < $Zombie::Sniper_SidearmRange) {
|
||||
//Target is getting into sidearm range... engage close range attacks
|
||||
%zombie.reallyFarTarget = 0;
|
||||
%zombie.CQCTarget = 1;
|
||||
%datablock.Move(%zombie);
|
||||
if(%zombie.canAltFire) {
|
||||
TWM2Lib_Zombie_Core("setZFlag", %zombie, "canAltFire", 0);
|
||||
schedule($Zombie::Sniper_RifleCooldown, 0, TWM2Lib_Zombie_Core, "setZFlag", %zombie, "canAltFire", 1);
|
||||
for(%i = 0; %i < $Zombie::Sniper_SidearmBurstCount; %i++) {
|
||||
%timeDelay = ($Zombie::Sniper_SidearmBurstTime / $Zombie::Sniper_SidearmBurstCount) * %i;
|
||||
%datablock.schedule(%timeDelay, "zFire_Alternate", %zombie);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(%dist < $Zombie::Sniper_MaximumEngageRange && %dist > $Zombie::Sniper_SidearmRange) {
|
||||
//Target is in Sniper Range... engage.
|
||||
%zombie.reallyFarTarget = 0;
|
||||
%zombie.CQCTarget = 0;
|
||||
if(vectorDist(%pos, %tPos) > $Zombie::Sniper_PreferedDistanceFromTarget) {
|
||||
//I'm a bit far out myself, let's move up while we engage.
|
||||
%datablock.Move(%zombie);
|
||||
}
|
||||
if(%zombie.canFireWeapon) {
|
||||
TWM2Lib_Zombie_Core("setZFlag", %zombie, "canFireWeapon", 0);
|
||||
schedule($Zombie::Sniper_RifleCooldown, 0, TWM2Lib_Zombie_Core, "setZFlag", %zombie, "canFireWeapon", 1);
|
||||
%datablock.zFire(%zombie);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//Target's a bit too far out, let's move up, but flag our AI to begin thinking about a new target
|
||||
%zombie.reallyFarTarget = 1;
|
||||
%zombie.CQCTarget = 0;
|
||||
%datablock.Move(%zombie);
|
||||
}
|
||||
}
|
||||
//No targets... Let's just wait.
|
||||
%zombie.aiLoop = %datablock.schedule(%zombie.updateTimeFrequency, "AI", %zombie);
|
||||
}
|
||||
|
||||
function SniperZombieArmor::Move(%datablock, %zombie) {
|
||||
|
|
@ -92,46 +168,63 @@ function SniperZombieArmor::Move(%datablock, %zombie) {
|
|||
return;
|
||||
}
|
||||
%pos = %zombie.getWorldBoxCenter();
|
||||
%closestClient = TWM2Lib_Zombie_Core("lookForTarget", %zombie);
|
||||
%closestDistance = getWord(%closestClient, 1);
|
||||
%closestClient = getWord(%closestClient, 0).Player;
|
||||
if(%closestDistance <= $zombie::detectDist) {
|
||||
if(%zombie.hastarget != 1) {
|
||||
%zombie.hastarget = 1;
|
||||
}
|
||||
TWM2Lib_Zombie_Core("playZAudio", %zombie, 100, 40);
|
||||
%vector = TWM2Lib_Zombie_Core("zombieGetFacingDirection", %zombie, %closestClient.getPosition());
|
||||
|
||||
if(Game.CheckModifier("SuperLunge") == 1) {
|
||||
%ld = $Zombie::LungeDistance * 5;
|
||||
}
|
||||
else {
|
||||
%ld = $Zombie::LungeDistance;
|
||||
}
|
||||
if(%closestDistance <= %ld && %zombie.canjump == 1) {
|
||||
%vector = vectorScale(%vector, 4);
|
||||
}
|
||||
%vector = vectorScale(%vector, %zombie.speed);
|
||||
%upvec = "150";
|
||||
if(%closestDistance <= %ld && %zombie.canjump == 1) {
|
||||
%upvec *= 2;
|
||||
TWM2Lib_Zombie_Core("setZFlag", %zombie, "canJump", 0);
|
||||
schedule($Zombie::BaseJumpCooldown, 0, TWM2Lib_Zombie_Core, "setZFlag", %zombie, "canJump", 1);
|
||||
}
|
||||
%tPos = %zombie.targetPlayer.getPosition();
|
||||
%upVec = "250";
|
||||
//Are we fighting in close quarters or not?
|
||||
if(%zombie.CQCTarget) {
|
||||
%zombie.setVelocity("0 0 0");
|
||||
//FaceTarget(%zombie, %target);
|
||||
TWM2Lib_Zombie_Core("zombieGetFacingDirection", %zombie, %tPos);
|
||||
%vector = vectorNormalize(vectorSub(%tPos, %zombie.getPosition()));
|
||||
%vector = vectorscale(%vector, %zombie.speed);
|
||||
%x = Getword(%vector, 0);
|
||||
%y = Getword(%vector, 1);
|
||||
%z = Getword(%vector, 2);
|
||||
if(%z >= 600) {
|
||||
%upvec = (%upvec * 5);
|
||||
}
|
||||
%nv1 = %y;
|
||||
%nv2 = (%x * -1);
|
||||
%vector = %nv1@" "@%nv2@" 0";
|
||||
%zombie.applyImpulse(%zombie.getPosition(), %vector);
|
||||
}
|
||||
else {
|
||||
%vector = TWM2Lib_Zombie_Core("zombieGetFacingDirection", %zombie, %tPos);
|
||||
//Scale to speed
|
||||
%vector = vectorScale(%vector, %zombie.speed);
|
||||
%x = getWord(%vector, 0);
|
||||
%y = getWord(%vector, 1);
|
||||
%vector = %x@" "@%y@" "@%upvec;
|
||||
%zombie.applyImpulse(%pos, %vector);
|
||||
%zombie.applyImpulse(%pos, %vector);
|
||||
}
|
||||
else if(%zombie.hastarget == 1) {
|
||||
%zombie.hastarget = 0;
|
||||
%zombie.zombieRmove = schedule(%zombie.updateTimeFrequency, %zombie, "TWM2Lib_Zombie_Core", "zRandomMoveLoop", %zombie);
|
||||
}
|
||||
%zombie.moveloop = %datablock.schedule(%zombie.updateTimeFrequency, "Move", %zombie);
|
||||
}
|
||||
|
||||
function SniperZombieArmor::zFire(%datablock, %zombie) {
|
||||
%target = %zombie.targetPlayer;
|
||||
%num = getRandom(250, 1000);
|
||||
%vec = vectorsub(VectorAdd(%target.getPosition(), "0 0 2.2"), %zombie.getMuzzlePoint(4));
|
||||
%accuracy = (vectorlen(%vec) / %num);
|
||||
%vec = vectoradd(%vec, vectorscale(%target.getvelocity(), %accuracy));
|
||||
%p = new TracerProjectile() {
|
||||
dataBlock = SniperZombieAcidShot;
|
||||
initialDirection = %vec;
|
||||
initialPosition = %zombie.getMuzzlePoint(4);
|
||||
sourceObject = %zombie;
|
||||
sourceSlot = 4;
|
||||
};
|
||||
ServerPlay3D(CentaurArtilleryFireSound, %zombie.getPosition());
|
||||
}
|
||||
|
||||
function SniperZombieArmor::zFire_Alternate(%datablock, %zombie) {
|
||||
%target = %zombie.targetPlayer;
|
||||
%num = getRandom(250, 1000);
|
||||
%vec = vectorsub(VectorAdd(%target.getPosition(), "0 0 1"), %zombie.getMuzzlePoint(4));
|
||||
%accuracy = (vectorlen(%vec) / %num);
|
||||
%vec = vectoradd(%vec, vectorscale(%target.getvelocity(), %accuracy));
|
||||
%p = new TracerProjectile() {
|
||||
dataBlock = SniperZombieAcidSidearmShot;
|
||||
initialDirection = %vec;
|
||||
initialPosition = %zombie.getMuzzlePoint(4);
|
||||
sourceObject = %zombie;
|
||||
sourceSlot = 4;
|
||||
};
|
||||
ServerPlay3D(CentaurArtilleryFireSound, %zombie.getPosition());
|
||||
}
|
||||
|
||||
//*****************************************************************
|
||||
|
|
@ -163,93 +256,6 @@ datablock PlayerData(FlareguideSniperZombieArmor) : SniperZombieArmor {
|
|||
max[Grenade] = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
function SniperZombiemovetotarget(%zombie){
|
||||
if(!isobject(%zombie))
|
||||
return;
|
||||
if(%zombie.getState() $= "dead")
|
||||
return;
|
||||
%pos = %zombie.getworldboxcenter();
|
||||
%closestClient = ZombieLookForTarget(%zombie);
|
||||
%closestDistance = getWord(%closestClient,1);
|
||||
%closestClient = getWord(%closestClient,0).Player;
|
||||
if(%closestDistance <= $zombie::detectDist){
|
||||
|
||||
if(%closestDistance < 50) { //runz0rs
|
||||
%TPos = %closestClient.getPosition();
|
||||
%tvel = %closestclient.getvelocity();
|
||||
%vec = vectorsub(%tpos,%pos);
|
||||
%dist = vectorlen(%vec);
|
||||
%velpredict = vectorscale(%tvel,(%dist / 50));
|
||||
%vector = vectoradd(%vec,%velpredict);
|
||||
%vector = vectornormalize(%vector);
|
||||
%x = getWord(%vector, 0);
|
||||
%y = getWord(%vector, 1);
|
||||
%finX = %x * -1;
|
||||
%finY = %y * -1;
|
||||
%finalVec = %finX SPC %finY SPC 0;
|
||||
%finalVec = VectorScale(%finalVec, $Zombie::DForwardSpeed * 3);
|
||||
//Z is unimportant
|
||||
%zombie.applyImpulse(%pos, %finalVec);
|
||||
}
|
||||
else {
|
||||
if(%zombie.hastarget != 1 && %closestdistance >= 50){
|
||||
SniperZombieFire(%zombie,%closestclient);
|
||||
%zombie.canjump = 0;
|
||||
schedule(4000, %zombie, "Zsetjump", %zombie);
|
||||
}
|
||||
if(%zombie.hastarget != 1){
|
||||
serverPlay3d("ZombieHOWL",%zombie.getWorldBoxCenter());
|
||||
%zombie.hastarget = 1;
|
||||
}
|
||||
%chance = (getrandom() * 20);
|
||||
if(%chance >= 19)
|
||||
serverPlay3d("ZombieMoan",%zombie.getWorldBoxCenter());
|
||||
|
||||
%vector = ZgetFacingDirection(%zombie,%closestClient,%pos);
|
||||
|
||||
if (%closestdistance >= 50 && %zombie.canjump == 1){
|
||||
SniperZombieFire(%zombie,%closestclient);
|
||||
%zombie.canjump = 0;
|
||||
schedule(4000, %zombie, "Zsetjump", %zombie);
|
||||
}
|
||||
if(%closestdistance > 175) { //only move toward my foe, if he is too
|
||||
%vector = vectorscale(%vector, $Zombie::DForwardSpeed); //far away
|
||||
%upvec = "150";
|
||||
%x = Getword(%vector,0);
|
||||
%y = Getword(%vector,1);
|
||||
%z = Getword(%vector,2);
|
||||
if(%z >= ($Zombie::DForwardSpeed / 3 * 2))
|
||||
%upvec = (%upvec * 5);
|
||||
%vector = %x@" "@%y@" "@%upvec;
|
||||
%zombie.applyImpulse(%pos, %vector);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(%zombie.hastarget == 1){
|
||||
%zombie.hastarget = 0;
|
||||
%zombie.zombieRmove = schedule(100, %zombie, "ZSetRandomMove", %zombie);
|
||||
}
|
||||
%zombie.moveloop = schedule(500, %zombie, "SniperZombiemovetotarget", %zombie);
|
||||
}
|
||||
|
||||
function SniperZombieFire(%zombie,%closestclient){
|
||||
%num = getRandom(250, 1000);
|
||||
%vec = vectorsub(VectorAdd(%closestclient.getPosition(), "0 0 2.2"),%zombie.getMuzzlePoint(4));
|
||||
%accuracy = (vectorlen(%vec) / %num);
|
||||
%vec = vectoradd(%vec, vectorscale(%closestclient.getvelocity(), %accuracy));
|
||||
%p = new TracerProjectile() { //TWM2 Sniper zombies use ALSWP Snipers :P
|
||||
dataBlock = SniperZombieAcidShot;
|
||||
initialDirection = %vec;
|
||||
initialPosition = %zombie.getMuzzlePoint(4);
|
||||
sourceObject = %zombie;
|
||||
sourceSlot = 4;
|
||||
};
|
||||
ServerPlay3D(ALSWPFireSound, %zombie.getPosition());
|
||||
}
|
||||
|
||||
|
||||
function FlareguideSniperZombieAcidShot::onExplode(%data, %proj, %pos, %mod) {
|
||||
Parent::OnExplode(%data, %proj, %pos, %mod);
|
||||
//Create the mini-pulses
|
||||
|
|
|
|||
Loading…
Reference in a new issue