Integrate NS Bloodsuckers

Add and update files for bloodsucker spawning option.
This commit is contained in:
worldwidesorrow
2021-08-18 09:47:25 -05:00
parent c10a436c71
commit 05118343fc
20 changed files with 3335 additions and 225 deletions

View File

@@ -41,4 +41,11 @@ if (!([_objPos] call DZE_SafeZonePosCheck)) then {
};
} forEach _positions;
};
// Bloodsuckers
if (DZE_Bloodsuckers) then {
if ((dayz_spawnBloodsuckers < DZE_BloodsuckersMaxLocal) && {dayz_CurrentNearBloodsuckers < DZE_BloodsuckersMaxNear} && {dayz_currentGlobalBloodsuckers < DZE_BloodsuckersMaxGlobal} && {_type in DZE_BloodsuckerBuildings} && {(random 1) < DZE_BloodsuckerChance}) then {
_objPos call mutant_generate;
};
};
};

View File

@@ -1,38 +1,43 @@
private ["_amount","_animalbody","_rawfoodtype","_qty"];
local _body = _this select 0;
local _qty = _this select 1;
local _rawfoodtype = "";
local _bodyType = typeOf _body;
local _time = diag_tickTime;
_animalbody = _this select 0;
_qty = _this select 1;
if (_animalbody isKindOf "zZombie_base") then {
_qty = 1;
_rawfoodtype = "ItemZombieParts";
} else {
_rawfoodtype = getText (configFile >> "CfgSurvival" >> "Meat" >> typeOf _animalbody >> "rawfoodtype");
call {
if (_body isKindOf "zZombie_base") exitWith {
_qty = 1;
_rawfoodtype = "ItemZombieParts";
};
if (_bodyType == "z_bloodsucker") exitWith {
_qty = 1;
_rawfoodtype = "ItemMutantHeart"; // toolbelt item
};
// default is animal
_rawfoodtype = getText (configFile >> "CfgSurvival" >> "Meat" >> _bodyType >> "rawfoodtype");
};
if (local _animalbody) then {
if (local _body) then {
for "_i" from 1 to _qty do {
_animalbody addMagazine _rawfoodtype;
if (_rawfoodtype == "ItemMutantHeart") then {
_body addWeapon _rawfoodtype;
} else {
_body addMagazine _rawfoodtype;
};
};
if (typeOf _animalbody in ["Cock","Hen"]) then {
_amount = (floor (random 4)) + 2;
if (_bodyType in ["Cock","Hen"]) then {
local _amount = (floor (random 4)) + 2;
for "_x" from 1 to _amount do {
_animalbody addMagazine "equip_feathers";
_body addMagazine "equip_feathers";
};
};
[time, _animalbody] spawn {
_timer = _this select 0;
_body = _this select 1;
_pos = getPosATL _body;
while {(count magazines _body > 0) && (time - _timer < 300)} do {
uiSleep 5;
};
hideBody _body;
uiSleep 10;
deleteVehicle _body;
true
while {((count magazines _body > 0) || (count weapons _body > 0)) && (diag_tickTime - _time < 300)} do {
uiSleep 5;
};
hideBody _body;
uiSleep 10;
deleteVehicle _body;
};

View File

@@ -0,0 +1,28 @@
/*
_localtargets and _remotetargets are set in player_zombieCheck.
The bloodsucker will move in the direction of the player assigned as target.
Players with a mutant heart on tool belt will not be targeted.
*/
local _mutant = _this;
if (isNull _mutant) exitWith {objNull}; // Prevent errors if mutant is suddenly deleted
local _localtargets = _mutant getVariable ["localtargets",[]];
local _remotetargets = _mutant getVariable ["remotetargets",[]];
local _targets = _localtargets + _remotetargets;
local _target = objNull;
local _scandist = 200;
{
if !(_x hasWeapon "ItemMutantHeart") then {
local _dist = _x distance _mutant;
if (_dist < _scandist) then {
_target = _x;
_scandist = _dist;
};
};
} count _targets;
_target

View File

@@ -0,0 +1,16 @@
// Select random position between 50 and 100 meters away from the building.
local _pos = [_this, 50, 100, 1] call fn_selectRandomLocation;
if (surfaceIsWater _pos) exitWith { diag_log "Mutant_Generate: Location is in water...abort"; };
// Create mutant
_agent = createAgent ["z_bloodsucker", _pos, [], 0, "NONE"];
_agent setDir (random 360);
_agent setPosATL _pos;
// Add to counts
dayz_spawnBloodsuckers = dayz_spawnBloodsuckers + 1;
dayz_CurrentNearBloodsuckers = dayz_CurrentNearBloodsuckers + 1;
dayz_currentGlobalBloodsuckers = dayz_currentGlobalBloodsuckers + 1;
//diag_log format ["Bloodsucker Counts: Current local - %1, Current near - %2, Current global - %3",dayz_spawnBloodsuckers,dayz_CurrentNearBloodsuckers,dayz_currentGlobalBloodsuckers];

View File

@@ -1,23 +1,16 @@
private ["_unit","_distance","_doRun","_pos","_listTalk","_zombie","_50","_localtargets","_remotetargets","_targets","_dis"];
_unit = _this select 0;
_distance = _this select 1;
_doRun = _this select 2;
_pos = _this select 3;
_listTalk = _pos nearEntities ["zZombie_Base",_distance];
local _unit = _this select 0;
local _distance = _this select 1;
local _doRun = _this select 2;
local _pos = _this select 3;
{
_distance = _distance max floor(_distance*.9);
_dis = _x distance _unit;
_zombie = _x;
local _dis = _x distance _unit;
call {
if (_dis < 51) exitwith {
if (_doRun) then {
_localtargets = _x getVariable ["localtargets",[]];
_remotetargets = _x getVariable ["remotetargets",[]];
_targets = _localtargets + _remotetargets;
local _localtargets = _x getVariable ["localtargets",[]];
local _remotetargets = _x getVariable ["remotetargets",[]];
local _targets = _localtargets + _remotetargets;
if (!(_unit in _targets)) then {
if !(local _x) then {
_remotetargets set [count _remotetargets,_unit];
@@ -28,16 +21,15 @@ _listTalk = _pos nearEntities ["zZombie_Base",_distance];
};
};
} else {
_zombie setVariable ["myDest",_pos,true];
_x setVariable ["myDest",_pos,true];
};
};
if ((_dis > 50) && {_dis <= 71}) exitwith {
_50 = round(random 100);
if (_50 < 50) then {
if (random 100 < 50) then {
if (_doRun) then {
_localtargets = _x getVariable ["localtargets",[]];
_remotetargets = _x getVariable ["remotetargets",[]];
_targets = _localtargets + _remotetargets;
local _localtargets = _x getVariable ["localtargets",[]];
local _remotetargets = _x getVariable ["remotetargets",[]];
local _targets = _localtargets + _remotetargets;
if (!(_unit in _targets)) then {
if !(local _x) then {
_remotetargets set [count _remotetargets,_unit];
@@ -48,14 +40,14 @@ _listTalk = _pos nearEntities ["zZombie_Base",_distance];
};
};
} else {
_zombie setVariable ["myDest",_pos,true];
_x setVariable ["myDest",_pos,true];
};
} else {
_zombie setVariable ["myDest",_pos,true];
_x setVariable ["myDest",_pos,true];
};
};
if (_dis > 70) exitwith {
_zombie setVariable ["myDest",_pos,true];
_x setVariable ["myDest",_pos,true];
};
};
} count _listTalk;
} count (_pos nearEntities ["Zed_Base",_distance]);

View File

@@ -0,0 +1,76 @@
/*
DayZ Epoch mutant attack script by JasonTM
Adapted from player_zombieAttack by facoptere
and Nightstalker melee attack effects by sumrak<at>nightstalkers.cz
*/
local _mutant = _this;
if (isNull _mutant) exitWith {}; // Prevent errors if mutant is deleted suddenly
local _damage = 0.5 + random (1.2); // Not sure about this. Maybe bloodsuckers should cause more damage.
local _wound = "";
local _dir = [_mutant,player] call BIS_Fnc_dirTo;
_mutant setDir _dir;
if (r_player_blood < (r_player_bloodTotal * 0.8)) then {
local _cnt = count (DAYZ_woundHit select 1);
local _index = floor (random _cnt);
_index = (DAYZ_woundHit select 1) select _index;
_wound = (DAYZ_woundHit select 0) select _index;
} else {
local _cnt = count (DAYZ_woundHit_ok select 1);
local _index = floor (random _cnt);
_index = (DAYZ_woundHit_ok select 1) select _index;
_wound = (DAYZ_woundHit_ok select 0) select _index;
};
local _pos = getPosATL player;
local _nearPlayer = false;
{
if (isPlayer _x && _x != player && {_x distance _pos < 100}) exitWith {_nearPlayer = true;};
} count playableUnits;
// Select a random attack sound
_sound = ["bloodatt0","bloodatt1","bloodatt2","bloodatt3"] call BIS_fnc_selectRandom;
// Broadcast hit noise and animation if a player is near
if (_nearPlayer) then {
[_mutant,_sound,0,false] call dayz_zombieSpeak;
//[objNull, _mutant, rplayMove, "AmelPercMstpSnonWnonDnon_amaterUder2"] call RE;
[nil, _mutant, rSwitchMove, "AmelPercMstpSnonWnonDnon_amaterUder2"] call RE;
} else {
[_mutant,_sound,0,true] call dayz_zombieSpeak;
//_mutant playMove "AmelPercMstpSnonWnonDnon_amaterUder2";
_mutant switchMove "AmelPercMstpSnonWnonDnon_amaterUder2";
};
uiSleep 0.3; // This sleep better coordinates the UI effects below with the animation and attack sound above.
if (DZE_BloodsuckerScreenEffect) then {cutRSC ["mutant_attack","PLAIN"];}; // the cool red slash marks that show up on screen.
"dynamicBlur" ppEffectEnable true;
"dynamicBlur" ppEffectAdjust [2];
"dynamicBlur" ppEffectCommit 0.1;
_pp = ppEffectCreate ["colorCorrections", 1553];
_pp ppEffectEnable true;
_pp ppEffectAdjust [1, 1, 0, [0.1, 0.0, 0.0, 1], [1.0, 0.5, 0.5, 0.1], [0.199, 0.587, 0.114, 0.0]];
_pp ppEffectCommit 0.1;
uiSleep 0.1;
_pp ppEffectAdjust [1, 1, 0, [0.1, 0.0, 0.0, 0.5], [1.0, 0.5, 0.5, 0.1], [0.199, 0.587, 0.114, 0.0]];
_pp ppEffectCommit 0.3;
uiSleep 0.3;
ppEffectDestroy _pp;
[player, _wound, _damage, _mutant, "zombie"] call fnc_usec_damageHandler;
uiSleep 0.2;
if (_nearPlayer) then {
[nil, _mutant, rSWITCHMOVE, ""] call RE;
} else {
_mutant switchMove "";
};
uiSleep 3;
"dynamicBlur" ppEffectEnable false;

View File

@@ -21,6 +21,22 @@ dayz_maxControlledZombies = dayz_maxLocalZombies; // This variable is also used
// Current loot spawns
dayz_currentWeaponHolders = count (_position nearObjects ["ReammoBox",_radius]);
// Current bloodsuckers
if (DZE_Bloodsuckers) then {
local _bloodsuckers = entities "z_bloodsucker";
dayz_currentGlobalBloodsuckers = count _bloodsuckers;
dayz_CurrentNearBloodsuckers = 0;
dayz_spawnBloodsuckers = 0;
{
if ((_x distance _position) < _radius && {alive _x}) then {
if (local _x) then {
dayz_spawnBloodsuckers = dayz_spawnBloodsuckers + 1;
};
dayz_CurrentNearBloodsuckers = dayz_CurrentNearBloodsuckers + 1;
};
} count _bloodsuckers;
};
// In vehicle check
local _vehicle = vehicle player;
local _inVehicle = (_vehicle != player);

View File

@@ -1,139 +1,144 @@
private ["_attacked","_chance","_near","_targeted","_localtargets","_remotetargets","_forcedSpeed","_vehicle","_refObj",
"_multiplier","_isAir","_hearingThreshold","_sightThreshold","_type","_dist","_attackDist",
"_targetedBySight","_targetedBySound","_targets","_last","_entHeight","_pHeight","_delta","_attackResult","_cantSee","_tPos","_zPos",
"_targetAngle","_inAngle","_lowBlood","_speedMin","_speedMax"];
// Check for near zombies and mutants and attack player
_vehicle = vehicle player;
_refObj = driver _vehicle;
_attacked = false; // at least one Z attacked the player
_near = false;
//_multiplier = 1;
_isAir = _vehicle isKindOf "Air";
_speedMin = DZE_ZombieSpeed select 0;
_speedMax = DZE_ZombieSpeed select 1;
local _vehicle = vehicle player;
local _inVehicle = _vehicle != player;
local _refObj = driver _vehicle;
local _attacked = false; // at least one Z attacked the player
local _isAir = _vehicle isKindOf "Air";
local _speedMin = DZE_ZombieSpeed select 0;
local _speedMax = DZE_ZombieSpeed select 1;
local _cantSee = false;
{
_forcedSpeed = if ((_speedMin != _speedMax) && {(_speedMin > 0) && (_speedMax > 0)}) then {((random (DZE_ZombieSpeed select 1)) max (DZE_ZombieSpeed select 0));} else {getNumber (configFile >> "CfgVehicles" >> (typeOf _x) >> "forcedSpeed");};
//_forcedSpeed = getNumber (configFile >> "CfgVehicles" >> (typeOf _x) >> "forcedSpeed");
//_hearingThreshold = getNumber (configFile >> "CfgVehicles" >> (typeOf _x) >> "hearingThreshold");
//_sightThreshold = getNumber (configFile >> "CfgVehicles" >> (typeOf _x) >> "sightThreshold");
if !(typeOf _x == "swarm_newBase") then {
_type = "zombie";
if (alive _x) then {
private ["_dist","_attackDist"];
_dist = _x distance _refObj;
_group = _x;
_chance = 1; //0 / dayz_monitorPeriod; // Z verbosity
_targetedBySight = false;
_targetedBySound = false;
_localtargets = _group getVariable ["localtargets",[]];
_remotetargets = _group getVariable ["remotetargets",[]];
_targets = _localtargets + _remotetargets;
if (_x distance player >= (dayz_areaAffect*2)) then {
if (speed _x < 4) then {
[_x,"idle",(_chance + 4),true] call dayz_zombieSpeak;
} else {
[_x,"chase",(_chance + 3),true] call dayz_zombieSpeak;
};
local _isZombie = _x isKindOf "zZombie_base";
local _isMutant = typeOf _x == "z_bloodsucker";
local _forcedSpeed = if ((_speedMin != _speedMax) && {(_speedMin > 0) && (_speedMax > 0)}) then {((random (DZE_ZombieSpeed select 1)) max (DZE_ZombieSpeed select 0));} else {getNumber (configFile >> "CfgVehicles" >> (typeOf _x) >> "forcedSpeed");};
local _dist = _x distance _refObj;
local _chance = 1; //0 / dayz_monitorPeriod; // Z verbosity
local _targetedBySight = false;
local _targetedBySound = false;
local _localtargets = _x getVariable ["localtargets",[]];
local _remotetargets = _x getVariable ["remotetargets",[]];
local _targets = _localtargets + _remotetargets;
if (_isMutant) then {
if (_dist <= 5) then {
local _skin = _x getVariable ["mutantSkin", "act_krovosos_new1"]; // Set textures locally on each client to prevent issues with RESec
_x setObjectTexture [0, format["\nst\ns_mutants\blood\%1.paa",_skin]];
} else {
_x setObjectTexture [0, ""];
local _sound = ["bloodgrowl0","bloodgrowl2","bloodgrowl3","bloodgrowl4","bloodforest1","bloodforest2","bloodforest3","bloodforest4"] call BIS_fnc_selectRandom;
[_x,_sound,(_chance + 4),false] call dayz_zombieSpeak;
};
};
if (_isZombie) then {
if (_x distance _refObj >= (dayz_areaAffect*2)) then {
if (speed _x < 4) then {
[_x,"idle",(_chance + 4),true] call dayz_zombieSpeak;
} else {
[_x,"chase",(_chance + 3),true] call dayz_zombieSpeak;
};
if (_x distance _refObj >= 3.3) then {_x setVariable ["speedLimit",_forcedSpeed,false];};
//if (!local _x) then {
if (_refObj in _targets) then {
_last = _x getVariable ["lastAttack", 0];
_entHeight = (getPosATL _x) select 2;
_pHeight = (getPosATL _refObj) select 2;
_delta = _pHeight - _entHeight;
_x setVariable ["speedLimit", 0, false];
if (_x distance _refObj <= 3) then {
//Force AI to Stand
_x setUnitPos "UP";
if !(animationState _x == "ZombieFeed") then {
if (((diag_tickTime - _last) > 1.5) && ((_delta < 1.5) && (_delta > -1.5))) then {
_cantSee = [_x,_refObj] call dayz_losCheck;
if (!_cantSee) then {
_attackResult = [_x, _type] spawn player_zombieAttack;
_x setVariable ["lastAttack", diag_tickTime];
};
};
if (_dist >= 3.3) then {_x setVariable ["speedLimit",_forcedSpeed,false];};
};
if (_refObj in _targets) then {
if (_isZombie) then {_x setVariable ["speedLimit", 0, false];};
if (_dist <= 3) then {
//Force AI to Stand
_x setUnitPos "UP";
if !(animationState _x == "ZombieFeed") then {
local _last = _x getVariable ["lastAttack", 0];
local _entHeight = (getPosATL _x) select 2;
local _pHeight = (getPosATL _refObj) select 2;
local _delta = _pHeight - _entHeight;
if (((diag_tickTime - _last) > 1.5) && ((_delta < 1.5) && (_delta > -1.5))) then {
_cantSee = [_refObj,_x] call dayz_losCheck;
if (!_cantSee) then {
if (_isZombie) then {
[_x, "zombie"] spawn player_zombieAttack;
} else {
if (!(_refObj hasWeapon "ItemMutantHeart") && !_inVehicle) then {
_x spawn player_mutantAttack;
};
};
} else {
_x setVariable ["speedLimit", _forcedSpeed, false];
_x setVariable ["lastAttack", diag_tickTime];
};
_attacked = true;
} else {
_x setVariable ["speedLimit", _forcedSpeed, false];
};
//};
//Block all target atteps while in a vehicle
if (!_isAir) then {
if !(_refObj in _targets) then {
//Noise Activation (zed is within players audial projection)
if (_dist < DAYZ_disAudial) then {
if (DAYZ_disAudial > 80) then {
};
} else {
if (_isZombie) then {_x setVariable ["speedLimit", _forcedSpeed, false];};
};
_attacked = true;
} else {
if (_isZombie) then {_x setVariable ["speedLimit", _forcedSpeed, false];};
};
//Block all target attempts while in an aircraft
if (!_isAir) then {
if !(_refObj in _targets) then {
//Noise Activation (zed is within players audial projection)
if (_dist < DAYZ_disAudial) then {
if (DAYZ_disAudial > 80) then {
_targetedBySound = true;
} else {
//if (DAYZ_disAudial > 6) then {
_chance = [_x,_dist,DAYZ_disAudial] call dayz_losChance;
//diag_log ("Visual Detection: " + str([_x,_dist]) + " " + str(_chance));
if ((random 1) < _chance) then {
//make sure the player isnt behind a building or wall if target is in the open always target if player is making too much noise
_cantSee = [_refObj,_x] call dayz_losCheck;
if (!_cantSee) then {
_targetedBySound = true;
} else {
//if (DAYZ_disAudial > 6) then {
_chance = [_x,_dist,DAYZ_disAudial] call dayz_losChance;
//diag_log ("Visual Detection: " + str([_x,_dist]) + " " + str(_chance));
if ((random 1) < _chance) then {
//make sure the player isnt behind a building or wall if target is in the open always target if player is making too much noise
_cantSee = [_refObj,_x] call dayz_losCheck;
if (!_cantSee) then {
_targetedBySound = true;
} else {
if (_dist < (DAYZ_disAudial / 2)) then {_targetedBySound = true;};
};
};
//};
if (_dist < (DAYZ_disAudial / 2)) then {_targetedBySound = true;};
};
};
//Sight Activation
if (_dist < DAYZ_disVisual ) then {
_chance = [_x,_dist,DAYZ_disVisual] call dayz_losChance;
if ((random 1) < _chance) then {
_tPos = getPosASL _vehicle;
_zPos = getPosASL _x;
_targetAngle = 30;
_inAngle = [_zPos,(direction _x),_targetAngle,_tPos] call fnc_inAngleSector;
if (_inAngle) then {
_cantSee = [_refObj,_x] call dayz_losCheck;
if (!_cantSee) then {_targetedBySight = true;};
};
};
};
//};
};
};
if (_targetedBySight or _targetedBySound) then {
[_x, "spotted", 0, false] call dayz_zombieSpeak;
//diag_log format["Zombie: %1, Distance: %2, Target Reason: Sight-%3,%5/Sound-%4,%6",(typeof _x),_dist,_targetedBySight,_targetedBySound,DAYZ_disVisual,DAYZ_disAudial];
switch (local _x) do {
case false: {
_remotetargets set [count _remotetargets,_refObj];
_x setVariable ["remotetargets",_remotetargets,true];
//Sight Activation
if (_dist < DAYZ_disVisual) then {
_chance = [_x,_dist,DAYZ_disVisual] call dayz_losChance;
if ((random 1) < _chance) then {
local _tPos = getPosASL _vehicle;
local _zPos = getPosASL _x;
local _targetAngle = 30;
local _inAngle = [_zPos,(direction _x),_targetAngle,_tPos] call fnc_inAngleSector;
if (_inAngle) then {
_cantSee = [_refObj,_x] call dayz_losCheck;
if (!_cantSee) then {_targetedBySight = true;};
};
case true: {
_localtargets set [count _localtargets,_refObj];
_x setVariable ["localtargets",_localtargets,false];
};
};
};
};
};
};
if (_targetedBySight || _targetedBySound) then {
local _sound = ["spotted","bloodgrowl1"] select _isMutant;
[_x, _sound, 0, false] call dayz_zombieSpeak;
//diag_log format["Zombie: %1, Distance: %2, Target Reason: Sight-%3,%5/Sound-%4,%6",(typeof _x),_dist,_targetedBySight,_targetedBySound,DAYZ_disVisual,DAYZ_disAudial];
if (local _x) then {
_localtargets set [count _localtargets,_refObj];
_x setVariable ["localtargets",_localtargets,false];
} else {
_remotetargets set [count _remotetargets,_refObj];
_x setVariable ["remotetargets",_remotetargets,true];
};
};
if (_isMutant && DZE_BloodsuckerDeleteNearTrader && isInTraderCity) then {deleteVehicle _x}; // Delete bloodsucker if the player is in a trader city
} forEach ((getPosATL _refObj) nearEntities ["Zed_Base",100]);
if (_attacked) then {
if (r_player_unconscious) then {
[_refObj, "scream", 6, false] call dayz_zombieSpeak;
} else {
_lowBlood = (r_player_blood / r_player_bloodTotal) < 0.5;
local _lowBlood = (r_player_blood / r_player_bloodTotal) < 0.5;
if (diag_ticktime - dayz_panicCooldown > 9 && _lowBlood) then {
//Prevents overlapping sounds (panic tracks are 4-9s, this script is called every 1s)
//50% chance every 9s
@@ -143,5 +148,5 @@ if (_attacked) then {
};
};
// return true if attacked or near. if so, player_monitor will perform its ridiculous 'while true' loop faster.
(_attacked OR _near)
// return true if attacked. if so, player_monitor will perform its ridiculous 'while true' loop faster.
_attacked