Files
zzz_REBIRTH__Utils/Scripts/ItemAction/ItemActionAttackRebirth.cs
2025-06-04 16:44:53 +09:30

816 lines
39 KiB
C#

using System.Collections.Generic;
public class ItemActionAttackRebirth
{
static float _KillExpMaxDist = 50f;
static float _NPCKillExpMod = 1f;
public static void Hit(
WorldRayHitInfo hitInfo_,
int attackerEntityId_,
EnumDamageTypes damageType_,
float blockDamage_,
float entityDamage_,
float staminaDamageMultiplier_,
float weaponCondition_,
float criticalHitChanceOLD_, // unused
float dismemberChance_,
string attackingDeviceMadeOf_,
DamageMultiplier damageMultiplier_,
List<string> buffActions_,
ItemActionAttack.AttackHitInfo attackDetails_,
int flags_ = 1,
int actionExp_ = 0, // unused
float actionExpBonus_ = 0f, // unused
ItemActionAttack rangeCheckedAction_ = null,
Dictionary<string, ItemActionAttack.Bonuses> toolBonuses_ = null,
ItemActionAttack.EnumAttackMode attackMode_ = ItemActionAttack.EnumAttackMode.RealNoHarvesting,
Dictionary<string, string> hitSoundOverrides_ = null,
int ownedEntityId_ = -1,
ItemValue damagingItemValue_ = null)
{
//Log.Out("ItemActionAttackPatches-Hit attackerEntityId_: " + attackerEntityId_);
//Log.Out("ItemActionAttackPatches-Hit ownedEntityId_: " + ownedEntityId_);
//Log.Out("ItemActionAttackPatches-Hit attackDetails_.WeaponTypeTag: " + attackDetails_.WeaponTypeTag);
//Log.Out("ItemActionAttackPatches-Hit weaponCondition_: " + weaponCondition_);
//Log.Out("ItemActionAttackPatches-Hit blockDamage_: " + blockDamage_);
//Log.Out("ItemActionAttackPatches-Hit entityDamage_: " + entityDamage_);
if (hitInfo_ == null || hitInfo_.tag == null) return;
bool bypassXP = false;
if (damagingItemValue_ != null && damagingItemValue_.ItemClass != null)
{
if (damagingItemValue_.ItemClass.Name.ToLower() == "autoturret" ||
damagingItemValue_.ItemClass.Name.ToLower() == "shotgunturret"
)
{
bypassXP = true;
}
}
World world = GameManager.Instance.World;
bool isNot_RNHOE = true;
if (attackMode_ == ItemActionAttack.EnumAttackMode.RealNoHarvestingOrEffects)
{
isNot_RNHOE = false;
attackMode_ = ItemActionAttack.EnumAttackMode.RealNoHarvesting;
}
if (attackDetails_ != null)
{
attackDetails_.itemsToDrop = null;
attackDetails_.bBlockHit = false;
attackDetails_.entityHit = null;
}
string particleCategory = null;
string surfaceCategory = null;
float lightValue = 1f;
Color particleColor = Color.white;
bool islphModLessThanOne = false;
EntityAlive attackingEntity = world.GetEntity(attackerEntityId_) as EntityAlive;
EntityNPCRebirth attackingNPC = attackingEntity as EntityNPCRebirth;
bool isInventoryItem = false;
if (attackingEntity != null)
{
if (damagingItemValue_ == null)
{
damagingItemValue_ = attackingEntity.inventory.holdingItemItemValue;
}
isInventoryItem = damagingItemValue_.Equals(attackingEntity.inventory.holdingItemItemValue);
}
bool isNotPlayerHit = true;
#region Hit -> Block/Terrain
if (GameUtils.IsBlockOrTerrain(hitInfo_.tag))
{
// Does this work outside of Unity Editor mode?
/*if (ItemAction.ShowDebugDisplayHit)
{
Vector3 position = Camera.main.transform.position;
DebugLines.Create(null, attackingEntity.RootTransform, position + Origin.position, hitInfo_.hit.pos, new Color(1f, 0.5f, 1f), new Color(1f, 0f, 1f), ItemAction.DebugDisplayHitSize * 2f, ItemAction.DebugDisplayHitSize, ItemAction.DebugDisplayHitTime);
}*/
// Nullify npc hire damage. Would be better to stop them from actually shooting/swinging in the first place
if (attackingNPC != null && attackingNPC.Buffs.GetCustomVar("$Leader") > 0 && attackDetails_.damage == 0)
{
//Log.Out("ItemActionAttackPatches-Hit 7a, _attackDetails: " + _attackDetails.damage);
return;
}
ChunkCluster chunkCluster = world.ChunkClusters[hitInfo_.hit.clrIdx];
if (chunkCluster == null) return;
Vector3i vecHitBlockPos = hitInfo_.hit.blockPos;
BlockValue blockValue = chunkCluster.GetBlock(vecHitBlockPos);
if (blockValue.isair && hitInfo_.hit.blockValue.Block.IsDistantDecoration && hitInfo_.hit.blockValue.damage >= hitInfo_.hit.blockValue.Block.MaxDamage - 1)
{
blockValue = hitInfo_.hit.blockValue;
world.SetBlockRPC(vecHitBlockPos, blockValue);
}
Block blockClass = blockValue.Block;
if (blockClass == null) return;
if (blockValue.ischild)
{
vecHitBlockPos = blockClass.multiBlockPos.GetParentPos(vecHitBlockPos, blockValue);
blockValue = chunkCluster.GetBlock(vecHitBlockPos);
blockClass = blockValue.Block;
if (blockClass == null) return;
}
if (blockValue.isair) return;
float lphModifier = world.GetLandProtectionHardnessModifier(hitInfo_.hit.blockPos, attackingEntity, world.GetGameManager().GetPersistentLocalPlayer());
if (world.IsWithinTraderArea(hitInfo_.hit.blockPos))
{
lphModifier = 0f;
}
if (blockClass.blockMaterial.id == "Mbedrock")
{
lphModifier = 0f;
}
if (lphModifier != 1f)
{
if (attackingEntity != null && attackMode_ != ItemActionAttack.EnumAttackMode.Simulate && attackingEntity is EntityPlayer && !damagingItemValue_.ItemClass.ignoreKeystoneSound && !damagingItemValue_.ToBlockValue().Block.IgnoreKeystoneOverlay)
{
attackingEntity.PlayOneShot("keystone_impact_overlay");
}
if (lphModifier < 1f)
{
islphModLessThanOne = true;
}
}
if (vecHitBlockPos != attackDetails_.hitPosition || lphModifier != attackDetails_.hardnessScale || blockValue.type != attackDetails_.blockBeingDamaged.type || (isInventoryItem && damagingItemValue_.SelectedAmmoTypeIndex != attackDetails_.ammoIndex))
{
float hardness = Mathf.Max(blockClass.GetHardness(), 0.1f) * lphModifier;
float dmgPerHit = blockDamage_ * (damageMultiplier_ != null ? damageMultiplier_.Get(blockClass.blockMaterial.DamageCategory) : 1f);
//Log.Out("ItemActionAttackPatches-Hit BEFORE dmgPerHit: " + dmgPerHit);
if (attackingEntity != null)
{
dmgPerHit *= attackingEntity.GetBlockDamageScale();
}
//Log.Out("ItemActionAttackPatches-Hit MID dmgPerHit: " + dmgPerHit);
if (toolBonuses_ != null && toolBonuses_.Count > 0)
{
dmgPerHit *= CalculateHarvestToolDamageBonus(toolBonuses_, blockClass.itemsToDrop);
attackDetails_.bHarvestTool = true;
}
//Log.Out("ItemActionAttackPatches-Hit AFTER dmgPerHit: " + dmgPerHit);
//Log.Out("ItemActionAttackPatches-Hit hardness: " + hardness);
//Log.Out("ItemActionAttackPatches-Hit (dmgPerHit / hardness): " + (dmgPerHit / hardness));
attackDetails_.damagePerHit = (!islphModLessThanOne) ? (dmgPerHit / hardness) : 0f;
attackDetails_.damage = 0f;
attackDetails_.hardnessScale = lphModifier;
attackDetails_.hitPosition = vecHitBlockPos;
attackDetails_.blockBeingDamaged = blockValue;
if (isInventoryItem)
{
attackDetails_.ammoIndex = damagingItemValue_.SelectedAmmoTypeIndex;
}
}
attackDetails_.raycastHitPosition = hitInfo_.hit.blockPos;
Block block2 = hitInfo_.fmcHit.blockValue.Block;
lightValue = world.GetLightBrightness(hitInfo_.fmcHit.blockPos);
particleColor = block2.GetColorForSide(hitInfo_.fmcHit.blockValue, hitInfo_.fmcHit.blockFace);
particleCategory = block2.GetParticleForSide(hitInfo_.fmcHit.blockValue, hitInfo_.fmcHit.blockFace);
MaterialBlock materialForSide = block2.GetMaterialForSide(hitInfo_.fmcHit.blockValue, hitInfo_.fmcHit.blockFace);
surfaceCategory = materialForSide.SurfaceCategory;
//NEW CODE - START
if (attackingEntity is EntityNPCRebirth)
{
staminaDamageMultiplier_ = 1;
}
//NEW CODE - END
float dmgPerHitStam = attackDetails_.damagePerHit * staminaDamageMultiplier_;
//Log.Out($"dmgPerHitStam: {dmgPerHitStam}, damagePerHit: {attackDetails_.damagePerHit}, staminaDamageMultiplier_: {staminaDamageMultiplier_}");
if (attackingEntity != null)
{
string dmgCategory = materialForSide.DamageCategory ?? string.Empty;
dmgPerHitStam = (int)EffectManager.GetValue(PassiveEffects.DamageModifier, damagingItemValue_, dmgPerHitStam, attackingEntity, null, FastTags<TagGroup.Global>.Parse(dmgCategory) | attackDetails_.WeaponTypeTag | hitInfo_.fmcHit.blockValue.Block.Tags);
}
dmgPerHitStam = ItemActionAttack.DegradationModifier(dmgPerHitStam, weaponCondition_);
dmgPerHitStam = (!islphModLessThanOne) ? Utils.FastMax(1f, dmgPerHitStam) : 0f;
attackDetails_.damage += dmgPerHitStam;
attackDetails_.bKilled = false;
attackDetails_.damageTotalOfTarget = blockValue.damage + attackDetails_.damage;
//Log.Out("ItemActionAttackPatches-Hit blockValue.damage: " + blockValue.damage);
//Log.Out("ItemActionAttackPatches-Hit attackDetails_.damage: " + attackDetails_.damage);
if (attackDetails_.damage > 0f)
{
Vector3 _hitFaceCenter;
Vector3 _hitFaceNormal;
BlockFace blockFaceFromHitInfo = GameUtils.GetBlockFaceFromHitInfo(vecHitBlockPos, blockValue, hitInfo_.hitCollider, hitInfo_.hitTriangleIdx, out _hitFaceCenter, out _hitFaceNormal);
int blockFaceTexture = chunkCluster.GetBlockFaceTexture(vecHitBlockPos, blockFaceFromHitInfo);
int curBlockDmg = blockValue.damage; // the amount of damage this block has currently taken. 0 if block hp is 100%
bool isOverkill = curBlockDmg >= blockClass.MaxDamage;
int entityIdThatDamaged = ((ownedEntityId_ != -1 && ownedEntityId_ != -2) ? ownedEntityId_ : attackerEntityId_);
int blockDmgAmt = (attackMode_ != ItemActionAttack.EnumAttackMode.Simulate) ? blockClass.DamageBlock(world, chunkCluster.ClusterIdx, vecHitBlockPos, blockValue, (int)attackDetails_.damage, entityIdThatDamaged, attackDetails_, attackDetails_.bHarvestTool) : 0;
//Log.Out($"blockVal curBlockDmg: {curBlockDmg}, blockDmgAmt: {blockDmgAmt}");
//Log.Out("ItemActionAttackPatches-Hit blockDmgAmt: " + blockDmgAmt);
if (blockDmgAmt == 0)
{
attackDetails_.damage = 0f;
}
else
{
attackDetails_.damage -= blockDmgAmt - curBlockDmg;
}
//Log.Out("ItemActionAttackPatches-Hit curBlockDmg: " + curBlockDmg);
//Log.Out("ItemActionAttackPatches-Hit attackDetails_.damage: " + attackDetails_.damage);
if (attackMode_ != ItemActionAttack.EnumAttackMode.Simulate && isNot_RNHOE && attackingEntity is EntityPlayerLocal && blockFaceTexture > 0 && blockClass.MeshIndex == 0 && (float)blockDmgAmt >= (float)blockClass.MaxDamage * 1f)
{
try
{
ParticleEffect particleEffect = new ParticleEffect("paint_block", hitInfo_.fmcHit.pos - Origin.position, Utils.BlockFaceToRotation(hitInfo_.fmcHit.blockFace), lightValue, particleColor, null, null);
particleEffect.opqueTextureId = BlockTextureData.list[blockFaceTexture].TextureID;
GameManager.Instance.SpawnParticleEffectClient(particleEffect, attackerEntityId_);
}
catch { }
}
attackDetails_.damageGiven = (!isOverkill) ? (blockDmgAmt - curBlockDmg) : 0;
// NEW CODE - START
RebirthVariables.damageGiven = attackDetails_.damageGiven;
// NEW CODE - END
attackDetails_.damageMax = blockClass.MaxDamage;
attackDetails_.bKilled = !isOverkill && blockDmgAmt >= blockClass.MaxDamage;
attackDetails_.itemsToDrop = blockClass.itemsToDrop;
attackDetails_.bBlockHit = true;
attackDetails_.materialCategory = blockClass.blockMaterial.SurfaceCategory;
if (attackingEntity != null && attackMode_ != ItemActionAttack.EnumAttackMode.Simulate)
{
attackingEntity.MinEventContext.ItemValue = damagingItemValue_;
attackingEntity.MinEventContext.BlockValue = blockValue;
attackingEntity.MinEventContext.Tags = blockClass.Tags;
if (attackDetails_.bKilled)
{
attackingEntity.FireEvent(MinEventTypes.onSelfDestroyedBlock, isInventoryItem);
attackingEntity.NotifyDestroyedBlock(attackDetails_);
}
else
{
attackingEntity.FireEvent(MinEventTypes.onSelfDamagedBlock, isInventoryItem);
}
}
}
}
#endregion
#region Hit -> Entity
else if (hitInfo_.tag.StartsWith("E_"))
{
string bodyPartName;
Entity hitEntity = ItemActionAttack.FindHitEntityNoTagCheck(hitInfo_, out bodyPartName);
// need to check CanDamageEntity to see if it's related to no hit bug
if (hitEntity == null || hitEntity.entityId == attackerEntityId_ || !hitEntity.CanDamageEntity(attackerEntityId_)) return;
EntityAlive hitEntityAlive = hitEntity as EntityAlive;
if (attackingEntity is EntityNPCRebirth && attackingEntity.HasAnyTags(FastTags<TagGroup.Global>.Parse("ranged")))
{
int npcLevel = (int)attackingEntity.Buffs.GetCustomVar("$FR_NPC_Level");
int headshotChance = npcLevel - 1;
int random = GameManager.Instance.World.GetGameRandom().RandomRange(1, 11);
string tagName = "E_BP_Head";
if (headshotChance < random)
{
tagName = RebirthVariables.bodyTags[random];
}
float numAccuracyModifier = float.Parse(RebirthVariables.customRangedNPCAccuracyModifier) / 100;
float baseValue = 100 * numAccuracyModifier;
int numMagazineSize = 0;
float roundsPerMinute = 60;
if (numMagazineSize == 0)
{
ItemActionRanged myAction = null;
myAction = (ItemActionRanged)attackingEntity.inventory.holdingItem.Actions[1];
ItemActionData _actionData = attackingEntity.inventory.holdingItemData.actionData[1];
ItemActionRanged.ItemActionDataRanged itemActionDataRanged = (ItemActionRanged.ItemActionDataRanged)_actionData;
float myDelay = 60f / EffectManager.GetValue(PassiveEffects.RoundsPerMinute, itemActionDataRanged.invData.itemValue, 60f / itemActionDataRanged.OriginalDelay, attackingEntity);
roundsPerMinute = 60 / myDelay;
numMagazineSize = (int)EffectManager.GetValue(PassiveEffects.MagazineSize, itemActionDataRanged.invData.itemValue, myAction.BulletsPerMagazine, attackingEntity);
}
if (numMagazineSize > 1)
{
baseValue = 60 * numAccuracyModifier;
int baseRoundsPerMinute = 60;
if (roundsPerMinute > baseRoundsPerMinute)
{
float multiplier = 1 - ((roundsPerMinute / baseRoundsPerMinute) / 15);
baseValue *= multiplier;
}
}
float missShotChance = baseValue + (npcLevel * 0.3f * numAccuracyModifier) * 10;
//Log.Out("ItemActionMeleePatches-hitTheTarget level: " + attackingEntity.Buffs.GetCustomVar("$FR_NPC_Level"));
//Log.Out("ItemActionMeleePatches-hitTheTarget A random: " + random);
//Log.Out("ItemActionMeleePatches-hitTheTarget missShotChance: " + missShotChance);
random = GameManager.Instance.World.GetGameRandom().RandomRange(1, 101);
//Log.Out("ItemActionMeleePatches-hitTheTarget B random: " + random);
if (missShotChance < random)
{
//Log.Out("ItemActionMeleePatches-hitTheTarget MISS");
return;
}
if (hitEntityAlive is EntityPlayer)
{
//Log.Out("ItemActionMeleePatches-hitTheTarget EntityName: " + hitEntityAlive.EntityName);
ProgressionValue progressionValue = hitEntityAlive.Progression.GetProgressionValue("perkDodge");
bool hitTarget = true;
if (progressionValue != null)
{
float chance = progressionValue.level * 5f;
random = GameManager.Instance.World.GetGameRandom().RandomRange(0, 101);
//Log.Out("ItemActionMeleePatches-hitTheTarget progressionValue.level: " + progressionValue.level);
//Log.Out("ItemActionMeleePatches-hitTheTarget chance: " + chance);
//Log.Out("ItemActionMeleePatches-hitTheTarget random: " + random);
if (random < chance)
{
//Log.Out("ItemActionMeleePatches-hitTheTarget EXIT");
hitTarget = false;
}
}
if (!hitTarget)
{
return;
}
}
}
Vector2 uvHit = Vector2.zero;
MeshCollider meshCollider = Voxel.phyxRaycastHit.collider as MeshCollider;
if (meshCollider != null && meshCollider.sharedMesh != null && meshCollider.sharedMesh.HasVertexAttribute(UnityEngine.Rendering.VertexAttribute.TexCoord0))
{
uvHit = Voxel.phyxRaycastHit.textureCoord;
}
DamageSourceEntity damageSourceEntity = new DamageSourceEntity(EnumDamageSource.External, damageType_, attackerEntityId_, hitInfo_.ray.direction, hitInfo_.transform.name, hitInfo_.hit.pos, uvHit);
damageSourceEntity.AttackingItem = damagingItemValue_;
damageSourceEntity.DismemberChance = dismemberChance_;
damageSourceEntity.CreatorEntityId = ownedEntityId_;
bool isCriticalHit = attackDetails_.isCriticalHit;
int entityDamage = (int)entityDamage_;
//Log.Out($"Entity Damage: {entityDamage}, attack mode: {attackMode_}");
if (attackingEntity != null && hitEntityAlive != null)
{
FastTags<TagGroup.Global> fastTags = FastTags<TagGroup.Global>.none;
if (hitEntityAlive.Health > 0)
{
fastTags = FastTags<TagGroup.Global>.Parse(damageSourceEntity.GetEntityDamageEquipmentSlotGroup(hitEntityAlive).ToStringCached());
}
entityDamage = (int)EffectManager.GetValue(PassiveEffects.DamageModifier, damagingItemValue_, entityDamage, attackingEntity, null, fastTags | attackDetails_.WeaponTypeTag | hitEntityAlive.EntityClass.Tags);
entityDamage = (int)EffectManager.GetValue(PassiveEffects.InternalDamageModifier, damagingItemValue_, entityDamage, hitEntityAlive, null, fastTags | damagingItemValue_.ItemClass.ItemTags);
}
if (!hitEntityAlive || hitEntityAlive.Health > 0)
{
entityDamage = Utils.FastMax(1, DifficultyModifier(entityDamage, world.GetEntity(attackerEntityId_), hitEntity));
}
else if (toolBonuses_ != null)
{
entityDamage = (int)(entityDamage * CalculateHarvestToolDamageBonus(toolBonuses_, EntityClass.list[hitEntity.entityClass].itemsToDrop));
}
// rebirth genetic level strengh mod
if (hitEntityAlive is EntityPlayer)
{
bool bMelee = hitEntityAlive.inventory.holdingItem.ItemTags.ToString().ToLower().Contains("melee");
if (bMelee)
{
//bool bSalvage = hitEntityAlive.inventory.holdingItem.ItemTags.ToString().ToLower().Contains("perkSalvageOperations"); // Unused at the moment?
entityDamage += entityDamage * RebirthUtilities.GetGeneticLevel("Strength") * 5 / 100;
}
}
bool hitEntityIsDead = hitEntity.IsDead();
int corpseHP = (hitEntityAlive != null) ? hitEntityAlive.DeathHealth : 0;
if (attackMode_ != ItemActionAttack.EnumAttackMode.Simulate)
{
if (attackingEntity != null)
{
MinEventParams minEventContext = attackingEntity.MinEventContext;
minEventContext.Other = hitEntityAlive;
minEventContext.ItemValue = damagingItemValue_;
minEventContext.StartPosition = hitInfo_.ray.origin;
}
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer &&
(attackingEntity as EntityPlayer == null || !attackingEntity.isEntityRemote) &&
hitEntity.isEntityRemote && rangeCheckedAction_ != null)
{
EntityPlayer hitPlayer = hitEntity as EntityPlayer;
if (hitPlayer != null) // if the target is a player
{
isNotPlayerHit = false;
// to do: check entity height and get a different ray origin. look ray might be too high for certain taller entitites that would cause them to consecutively miss shorter entities
// nevermind, wrong place...
Ray lookRay = attackingEntity.GetLookRay();
lookRay.origin -= lookRay.direction * 0.15f;
float maxRange = Utils.FastMax(rangeCheckedAction_.Range, rangeCheckedAction_.BlockRange) * ItemActionAttack.attackRangeMultiplier; // Why are we multiplying by 1f?
string buffActionsContext = null;
List<string> buffActions = buffActions_;
if (buffActions != null)
{
if (hitEntityAlive != null)
{
buffActionsContext = ((bodyPartName != null) ? GameUtils.GetChildTransformPath(hitEntity.transform, hitInfo_.transform) : null);
}
else
{
buffActions = null;
}
}
if (attackingEntity != null)
{
attackingEntity.FireEvent(MinEventTypes.onSelfAttackedOther, isInventoryItem);
if (hitEntityAlive != null && hitEntityAlive.RecordedDamage.Strength > 0)
{
attackingEntity.FireEvent(MinEventTypes.onSelfDamagedOther, isInventoryItem);
}
}
if (!hitEntityIsDead && hitEntity.IsDead() && attackingEntity != null)
{
attackingEntity.FireEvent(MinEventTypes.onSelfKilledOther, isInventoryItem);
AddKillExpNPC(attackingNPC, hitEntityAlive);
}
surfaceCategory = ((!hitEntityAlive || hitEntityAlive.RecordedDamage.ArmorDamage <= hitEntityAlive.RecordedDamage.Strength) ? EntityClass.list[hitEntity.entityClass].Properties.Values["SurfaceCategory"] : "metal");
particleCategory = surfaceCategory;
lightValue = hitEntity.GetLightBrightness();
string particleEffectName = $"impact_{attackingDeviceMadeOf_}_on_{particleCategory}";
string soundName = ((surfaceCategory != null) ? $"{attackingDeviceMadeOf_}hit{surfaceCategory}" : null);
if (hitSoundOverrides_ != null && hitSoundOverrides_.ContainsKey(surfaceCategory))
{
soundName = hitSoundOverrides_[surfaceCategory];
}
ParticleEffect particleEffect2 = new ParticleEffect(particleEffectName, hitInfo_.fmcHit.pos, Utils.BlockFaceToRotation(hitInfo_.fmcHit.blockFace), lightValue, particleColor, soundName, null);
hitPlayer.ServerNetSendRangeCheckedDamage(lookRay.origin, maxRange, damageSourceEntity, entityDamage, isCriticalHit, buffActions, buffActionsContext, particleEffect2);
//Log.Out($"Rebirth Hit ServerNetSend - attackingEntity: {attackingEntity}, hitEntity: {hitEntity} entityDamage: {entityDamage}, stacktrace: {System.Environment.StackTrace}");
}
}
if (isNotPlayerHit)
{
// rebirth mod to recalculate damage
if (hitInfo_.tag.Equals("E_BP_Head"))
{
EntityPlayer sourcePlayer = world.GetEntity(damageSourceEntity.getEntityId()) as EntityPlayer;
if (sourcePlayer != null)
{
bool isLongRangeWeapon = sourcePlayer.inventory.holdingItem.HasAnyTags(FastTags<TagGroup.Global>.Parse("WeaponTier3LongRangeRifles"));
if (isLongRangeWeapon)
{
int activeClassID = (int)sourcePlayer.Buffs.GetCustomVar("$ActiveClass_FR");
if (RebirthUtilities.IsClassActive(activeClassID))
{
ProgressionValue progressionValue = sourcePlayer.Progression.GetProgressionValue("FuriousRamsayPerkLongRangeRifles");
if (progressionValue != null)
{
int progressionLevel = progressionValue.Level;
float damageMultiplier = progressionLevel * 0.025f;
bool isSingShotWeapon = sourcePlayer.inventory.holdingItem.HasAnyTags(FastTags<TagGroup.Global>.Parse("SingleShot"));
if (isSingShotWeapon) damageMultiplier *= 2f;
entityDamage *= (int)(1f + damageMultiplier);
}
}
}
}
}
int dmgResult = hitEntity.DamageEntity(damageSourceEntity, entityDamage, isCriticalHit);
//Log.Out($"Rebirth Hit - attackingEntity: {attackingEntity}, hitEntity: {hitEntity} dmg entity result: {dmgResult}, stacktrace: {System.Environment.StackTrace}");
if (dmgResult != -1 && attackingEntity != null)
{
MinEventParams minEventContext2 = attackingEntity.MinEventContext;
minEventContext2.Other = hitEntityAlive;
minEventContext2.ItemValue = damagingItemValue_;
minEventContext2.StartPosition = hitInfo_.ray.origin;
if (ownedEntityId_ != -1)
{
damagingItemValue_.FireEvent(MinEventTypes.onSelfAttackedOther, attackingEntity.MinEventContext);
}
attackingEntity.FireEvent(MinEventTypes.onSelfAttackedOther, isInventoryItem);
if (hitEntityAlive != null && hitEntityAlive.RecordedDamage.Strength > 0)
{
attackingEntity.FireEvent(MinEventTypes.onSelfDamagedOther, isInventoryItem);
}
}
if (!hitEntityIsDead && hitEntity.IsDead() && attackingEntity != null)
{
attackingEntity.FireEvent(MinEventTypes.onSelfKilledOther, isInventoryItem);
AddKillExpNPC(attackingNPC, hitEntityAlive);
}
if (dmgResult != -1 && hitEntityAlive != null && buffActions_ != null && buffActions_.Count > 0)
{
for (int i = 0; i < buffActions_.Count; i++)
{
BuffClass buff = BuffManager.GetBuff(buffActions_[i]);
if (buff != null)
{
float originalValue = 1f;
originalValue = EffectManager.GetValue(PassiveEffects.BuffProcChance, null, originalValue, attackingEntity, null, FastTags<TagGroup.Global>.Parse(buff.Name));
if (hitEntityAlive.rand.RandomFloat <= originalValue)
{
hitEntityAlive.Buffs.AddBuff(buffActions_[i], attackingEntity.entityId);
}
}
}
}
}
}
surfaceCategory = (!hitEntityAlive || hitEntityAlive.RecordedDamage.ArmorDamage <= hitEntityAlive.RecordedDamage.Strength) ? EntityClass.list[hitEntity.entityClass].Properties.Values["SurfaceCategory"] : "metal";
particleCategory = surfaceCategory;
lightValue = hitEntity.GetLightBrightness();
EntityPlayer attackingPlayer = attackingEntity as EntityPlayer;
if (attackingPlayer != null) // The attacker is a Player
{
if (hitEntityIsDead && hitEntity.IsDead() && (bool)hitEntityAlive && hitEntityAlive.DeathHealth + entityDamage > -1 * EntityClass.list[hitEntity.entityClass].DeadBodyHitPoints)
{
attackDetails_.damageTotalOfTarget = -1 * hitEntityAlive.DeathHealth;
attackDetails_.damageGiven = corpseHP + Mathf.Min(EntityClass.list[hitEntity.entityClass].DeadBodyHitPoints, Mathf.Abs(hitEntityAlive.DeathHealth));
attackDetails_.damageMax = EntityClass.list[hitEntity.entityClass].DeadBodyHitPoints;
attackDetails_.bKilled = -1 * hitEntityAlive.DeathHealth >= EntityClass.list[hitEntity.entityClass].DeadBodyHitPoints;
attackDetails_.itemsToDrop = EntityClass.list[hitEntity.entityClass].itemsToDrop;
attackDetails_.entityHit = hitEntity;
attackDetails_.materialCategory = surfaceCategory;
}
if (!hitEntityIsDead && (hitEntityAlive.IsDead() || hitEntityAlive.Health <= 0) && EntityClass.list.ContainsKey(hitEntity.entityClass))
{
if ((flags_ & 2) > 0)
{
float value = EffectManager.GetValue(PassiveEffects.ElectricalTrapXP, attackingPlayer.inventory.holdingItemItemValue, 0f, attackingPlayer);
if (value > 0f)
{
if (!bypassXP)
{
attackingPlayer.AddKillXP(hitEntityAlive, value);
}
}
}
else
{
if (!bypassXP)
{
attackingPlayer.AddKillXP(hitEntityAlive);
}
}
}
}
if (hitEntity is EntityDrone)
{
attackDetails_.entityHit = hitEntity;
}
}
#endregion
if ((flags_ & 8) > 0)
{
isNot_RNHOE = false;
}
// Spawn Particle Effect
if (isNotPlayerHit && attackMode_ != ItemActionAttack.EnumAttackMode.Simulate && isNot_RNHOE && particleCategory != null && ((attackDetails_.bBlockHit && !attackDetails_.bKilled) || !attackDetails_.bBlockHit))
{
string particleName = $"impact_{attackingDeviceMadeOf_}_on_{particleCategory}";
if (attackMode_ == ItemActionAttack.EnumAttackMode.RealAndHarvesting && (flags_ & 4) > 0 && ParticleEffect.IsAvailable(particleName + "_harvest"))
{
particleName += "_harvest";
}
string soundName2 = ((surfaceCategory != null) ? $"{attackingDeviceMadeOf_}hit{surfaceCategory}" : null);
if (hitSoundOverrides_ != null && hitSoundOverrides_.ContainsKey(surfaceCategory))
{
soundName2 = hitSoundOverrides_[surfaceCategory];
}
world.GetGameManager().SpawnParticleEffectServer(new ParticleEffect(particleName, hitInfo_.fmcHit.pos, Utils.BlockFaceToRotation(hitInfo_.fmcHit.blockFace), lightValue, particleColor, soundName2, null), attackerEntityId_, _forceCreation: false, _worldSpawn: true);
}
// Update the attacking entity's toolbelt
if ((flags_ & 1) > 0 && attackingEntity != null && attackingEntity.inventory != null)
{
attackingEntity.inventory.CallOnToolbeltChangedInternal();
}
}
static int DifficultyModifier(int _strength, Entity _attacker, Entity _target)
{
if (_attacker == null || _target == null
|| (_attacker.IsClientControlled() && _target.IsClientControlled())
|| (!_attacker.IsClientControlled() && !_target.IsClientControlled())) return _strength;
int difficultyLevel = GameStats.GetInt(EnumGameStats.GameDifficulty);
if (_attacker.IsClientControlled())
{
switch (difficultyLevel)
{
case 0:
_strength = Mathf.RoundToInt((float)_strength * 2f);
break;
case 1:
_strength = Mathf.RoundToInt((float)_strength * 1.5f);
break;
case 3:
_strength = Mathf.RoundToInt((float)_strength * 0.83f);
break;
case 4:
_strength = Mathf.RoundToInt((float)_strength * 0.66f);
break;
case 5:
_strength = Mathf.RoundToInt((float)_strength * 0.5f);
break;
}
}
else
{
switch (difficultyLevel)
{
case 0:
_strength = Mathf.RoundToInt((float)_strength * 0.5f);
break;
case 1:
_strength = Mathf.RoundToInt((float)_strength * 0.75f);
break;
case 3:
_strength = Mathf.RoundToInt((float)_strength * 1.5f);
break;
case 4:
_strength = Mathf.RoundToInt((float)_strength * 2f);
break;
case 5:
_strength = Mathf.RoundToInt((float)_strength * 2.5f);
break;
}
}
return _strength;
}
static float CalculateHarvestToolDamageBonus(Dictionary<string, ItemActionAttack.Bonuses> _toolBonuses, Dictionary<EnumDropEvent, List<Block.SItemDropProb>> _harvestItems)
{
if (!_harvestItems.ContainsKey(EnumDropEvent.Harvest)) return 1f;
List<Block.SItemDropProb> list = _harvestItems[EnumDropEvent.Harvest];
for (int i = 0; i < list.Count; i++)
{
if (list[i].toolCategory != null && _toolBonuses.ContainsKey(list[i].toolCategory))
{
return _toolBonuses[list[i].toolCategory].Damage;
}
}
return 1f;
}
static void AddKillExpNPC(EntityNPCRebirth attackingNPC, EntityAlive entityTarget)
{
if (attackingNPC == null || entityTarget == null) return;
int leaderID = RebirthUtilities.GetLeader(attackingNPC);
if (leaderID <= 0) return;
var leaderPlayer = attackingNPC.world.GetEntity(leaderID) as EntityPlayer;
if (leaderPlayer == null)
{
Log.Warning($"NPC has leader, unable to locate the player. Leader id: {leaderID}");
return;
}
float distanceEntity = leaderPlayer.GetDistance(attackingNPC);
if (distanceEntity > _KillExpMaxDist) return; // too far away
bool isNaturalSelectionCountingOn = RebirthUtilities.IsNaturalSelectionCountingOn();
/*if (isNaturalSelectionCountingOn)
{
Log.Out($"ItemActionAttackRebirth-AddKillExpNPC $NaturalSelection_FR: {leaderPlayer.Buffs.GetCustomVar("$NaturalSelection_FR")}");
int numNS = (int)leaderPlayer.Buffs.GetCustomVar("$NaturalSelection_FR") + 1;
leaderPlayer.Buffs.SetCustomVar("$NaturalSelection_FR", numNS);
RebirthVariables.localConstants["$varFuriousRamsayTheyGrowStrongerKills_Cst"] = numNS;
}*/
float expMod = _NPCKillExpMod;
if (RebirthUtilities.IsHordeNight()) expMod *= RebirthVariables.hordeNightXPMultiplier;
float partyMultiplierOption = 1; // float.Parse(RebirthVariables.customPartyXPMultiplier) / 100;
expMod = expMod * partyMultiplierOption;
float experienceGained = entityTarget.ExperienceValue * expMod;
//Log.Out($"ItemActionAttackRebirth-AddKillExpNPC entity xp: {entityTarget.ExperienceValue}");
//Log.Out($"ItemActionAttackRebirth-AddKillExpNPC partyMultiplierOption: {partyMultiplierOption}");
//Log.Out($"ItemActionAttackRebirth-AddKillExpNPC _NPCKillExpMod: {_NPCKillExpMod}");
//Log.Out($"ItemActionAttackRebirth-AddKillExpNPC _HordeNightExpMod: {RebirthVariables.hordeNightXPMultiplier}");
//Log.Out($"ItemActionAttackRebirth-AddKillExpNPC expMod: {expMod}");
//Log.Out($"ItemActionAttackRebirth-AddKillExpNPC experienceGained: {experienceGained}");
leaderPlayer.AddKillXP(entityTarget, expMod);
leaderPlayer.Progression.bProgressionStatsChanged = true;
leaderPlayer.bPlayerStatsChanged = true;
if (entityTarget is EntityPlayer)
leaderPlayer.KilledPlayers++;
else
leaderPlayer.KilledZombies++;
}
}