Upload from upload_mods.ps1

This commit is contained in:
Nathaniel Cosford
2025-06-04 16:13:32 +09:30
commit 7345f42201
470 changed files with 51966 additions and 0 deletions

View File

@@ -0,0 +1,738 @@
using KFCommonUtilityLib.Scripts.StaticManagers;
using System.Collections.Generic;
using UnityEngine;
namespace KFCommonUtilityLib.Scripts.Utilities
{
/// <summary>
/// This new script make following changes:
/// - projectile ItemValue fields are reused for custom passive calculation:
/// -- Meta => launcher ItemClass id
/// -- SelectedAmmoIndex => launcher action index
/// -- Activated => launcher data strain perc
/// -- cosmetics and mods reference launcher ItemValue
/// -- Quality and Durability is copied from launcher ItemValue
/// - MinEventParams.itemActionData is set to correct launcher data.
/// </summary>
public class CustomProjectileMoveScript : ProjectileMoveScript
{
public override void checkCollision()
{
if (this.firingEntity == null || state != State.Active || gameManager == null)
return;
World world = gameManager?.World;
if (world == null)
{
return;
}
Vector3 checkPos;
if (bOnIdealPos)
{
checkPos = transform.position + Origin.position;
}
else
{
checkPos = idealPosition;
}
Vector3 dir = checkPos - previousPosition;
float magnitude = dir.magnitude;
if (magnitude < 0.04f)
{
return;
}
EntityAlive firingEntity = (EntityAlive)this.firingEntity;
Ray ray = new Ray(previousPosition, dir.normalized);
waterCollisionParticles.CheckCollision(ray.origin, ray.direction, magnitude, (firingEntity != null) ? firingEntity.entityId : (-1));
int prevLayer = 0;
if (firingEntity != null && firingEntity.emodel != null)
{
prevLayer = firingEntity.GetModelLayer();
firingEntity.SetModelLayer(2);
}
int hitmask = ((hmOverride == 0) ? 80 : hmOverride);
bool flag = Voxel.Raycast(world, ray, magnitude, -538750997, hitmask, 0);
if (firingEntity != null && firingEntity.emodel != null)
{
firingEntity.SetModelLayer(prevLayer);
}
if (flag && (GameUtils.IsBlockOrTerrain(Voxel.voxelRayHitInfo.tag) || Voxel.voxelRayHitInfo.tag.StartsWith("E_")))
{
if (firingEntity != null && !firingEntity.isEntityRemote)
{
firingEntity.MinEventContext.Other = ItemActionAttack.FindHitEntity(Voxel.voxelRayHitInfo) as EntityAlive;
firingEntity.MinEventContext.ItemActionData = actionData;
firingEntity.MinEventContext.ItemValue = itemValueLauncher;
firingEntity.MinEventContext.Position = Voxel.voxelRayHitInfo.hit.pos;
ItemActionAttack.AttackHitInfo attackHitInfo = new ItemActionAttack.AttackHitInfo
{
WeaponTypeTag = ItemActionAttack.RangedTag
};
float strainPerc = itemValueProjectile.Activated / (float)byte.MaxValue;
MultiActionProjectileRewrites.ProjectileHit(Voxel.voxelRayHitInfo,
ProjectileOwnerID,
EnumDamageTypes.Piercing,
Mathf.Lerp(1f, MultiActionProjectileRewrites.GetProjectileDamageBlock(itemActionProjectile, itemValueProjectile, ItemActionAttack.GetBlockHit(world, Voxel.voxelRayHitInfo), firingEntity, actionData.indexInEntityOfAction), strainPerc),
Mathf.Lerp(1f, MultiActionProjectileRewrites.GetProjectileDamageEntity(itemActionProjectile, itemValueProjectile, firingEntity, actionData.indexInEntityOfAction), strainPerc),
1f,
1f,
MultiActionReversePatches.ProjectileGetValue(PassiveEffects.CriticalChance, itemValueProjectile, itemProjectile.CritChance.Value, firingEntity, null, itemProjectile.ItemTags, true, false),
ItemAction.GetDismemberChance(actionData, Voxel.voxelRayHitInfo),
itemProjectile.MadeOfMaterial.SurfaceCategory,
itemActionProjectile.GetDamageMultiplier(),
getBuffActions(),
attackHitInfo,
1,
itemActionProjectile.ActionExp,
itemActionProjectile.ActionExpBonusMultiplier,
null,
null,
ItemActionAttack.EnumAttackMode.RealNoHarvesting,
null,
-1,
itemValueProjectile,
itemValueLauncher);
if (firingEntity.MinEventContext.Other == null)
{
firingEntity.FireEvent(MinEventTypes.onSelfPrimaryActionMissEntity, false);
}
firingEntity.FireEvent(MinEventTypes.onProjectileImpact, false);
MinEventParams.CachedEventParam.Self = firingEntity;
MinEventParams.CachedEventParam.Position = Voxel.voxelRayHitInfo.hit.pos;
MinEventParams.CachedEventParam.ItemValue = itemValueProjectile;
MinEventParams.CachedEventParam.ItemActionData = actionData;
MinEventParams.CachedEventParam.Other = firingEntity.MinEventContext.Other;
itemProjectile.FireEvent(MinEventTypes.onProjectileImpact, MinEventParams.CachedEventParam);
if (itemActionProjectile.Explosion.ParticleIndex > 0)
{
Vector3 vector3 = Voxel.voxelRayHitInfo.hit.pos - dir.normalized * 0.1f;
Vector3i vector3i = World.worldToBlockPos(vector3);
if (!world.GetBlock(vector3i).isair)
{
BlockFace blockFace;
vector3i = Voxel.OneVoxelStep(vector3i, vector3, -dir.normalized, out vector3, out blockFace);
}
gameManager.ExplosionServer(Voxel.voxelRayHitInfo.hit.clrIdx, vector3, vector3i, Quaternion.identity, itemActionProjectile.Explosion, ProjectileOwnerID, 0f, false, itemValueProjectile);
SetState(State.Dead);
return;
}
if (itemProjectile.IsSticky)
{
GameRandom gameRandom = world.GetGameRandom();
if (GameUtils.IsBlockOrTerrain(Voxel.voxelRayHitInfo.tag))
{
if (gameRandom.RandomFloat < MultiActionReversePatches.ProjectileGetValue(PassiveEffects.ProjectileStickChance, itemValueProjectile, 0.5f, firingEntity, null, itemProjectile.ItemTags | FastTags<TagGroup.Global>.Parse(Voxel.voxelRayHitInfo.fmcHit.blockValue.Block.blockMaterial.SurfaceCategory), true, false))
{
RestoreProjectileValue();
ProjectileID = ProjectileManager.AddProjectileItem(transform, -1, Voxel.voxelRayHitInfo.hit.pos, dir.normalized, itemValueProjectile.type);
SetState(State.Sticky);
}
else
{
gameManager.SpawnParticleEffectServer(new ParticleEffect("impact_metal_on_wood", Voxel.voxelRayHitInfo.hit.pos, Utils.BlockFaceToRotation(Voxel.voxelRayHitInfo.fmcHit.blockFace), 1f, Color.white, string.Format("{0}hit{1}", Voxel.voxelRayHitInfo.fmcHit.blockValue.Block.blockMaterial.SurfaceCategory, itemProjectile.MadeOfMaterial.SurfaceCategory), null), firingEntity.entityId, false, false);
SetState(State.Dead);
}
}
else if (gameRandom.RandomFloat < MultiActionReversePatches.ProjectileGetValue(PassiveEffects.ProjectileStickChance, itemValueProjectile, 0.5f, firingEntity, null, itemProjectile.ItemTags, true, false))
{
RestoreProjectileValue();
ProjectileID = ProjectileManager.AddProjectileItem(transform, -1, Voxel.voxelRayHitInfo.hit.pos, dir.normalized, itemValueProjectile.type);
Utils.SetLayerRecursively(ProjectileManager.GetProjectile(ProjectileID).gameObject, 14, null);
SetState(State.Sticky);
}
else
{
gameManager.SpawnParticleEffectServer(new ParticleEffect("impact_metal_on_wood", Voxel.voxelRayHitInfo.hit.pos, Utils.BlockFaceToRotation(Voxel.voxelRayHitInfo.fmcHit.blockFace), 1f, Color.white, "bullethitwood", null), firingEntity.entityId, false, false);
SetState(State.Dead);
}
}
else
{
SetState(State.Dead);
}
}
else
{
SetState(State.Dead);
}
if (state == State.Active)
{
SetState(State.Dead);
}
}
previousPosition = checkPos;
}
private void RestoreProjectileValue()
{
itemValueProjectile.Modifications = ItemValue.emptyItemValueArray;
itemValueProjectile.CosmeticMods = ItemValue.emptyItemValueArray;
itemValueProjectile.Quality = 0;
itemValueProjectile.UseTimes = 0;
itemValueProjectile.Meta = 0;
itemValueProjectile.SelectedAmmoTypeIndex = 0;
}
}
public static class MultiActionProjectileRewrites
{
public static void ProjectileHit(WorldRayHitInfo hitInfo, int _attackerEntityId, EnumDamageTypes _damageType, float _blockDamage,
float _entityDamage, float _staminaDamageMultiplier, float _weaponCondition, float _criticalHitChanceOLD,
float _dismemberChance, string _attackingDeviceMadeOf, DamageMultiplier _damageMultiplier,
List<string> _buffActions, ItemActionAttack.AttackHitInfo _attackDetails, int _flags = 1, int _actionExp = 0,
float _actionExpBonus = 0f, ItemActionAttack rangeCheckedAction = null,
Dictionary<string, ItemActionAttack.Bonuses> _toolBonuses = null,
ItemActionAttack.EnumAttackMode _attackMode = ItemActionAttack.EnumAttackMode.RealNoHarvesting,
Dictionary<string, string> _hitSoundOverrides = null, int ownedEntityId = -1, ItemValue projectileValue = null, ItemValue launcherValue = null)
{
if (_attackDetails != null)
{
_attackDetails.hitPosition = Vector3i.zero;
_attackDetails.bKilled = false;
}
if (hitInfo == null || hitInfo.tag == null)
{
return;
}
World world = GameManager.Instance.World;
bool canHarvest = true;
if (_attackMode == ItemActionAttack.EnumAttackMode.RealNoHarvestingOrEffects)
{
canHarvest = false;
_attackMode = ItemActionAttack.EnumAttackMode.RealNoHarvesting;
}
if (_attackDetails != null)
{
_attackDetails.itemsToDrop = null;
_attackDetails.bBlockHit = false;
_attackDetails.entityHit = null;
}
string blockFaceParticle = null;
string surfaceCategory = null;
float lightValueAtBlockPos = 1f;
Color blockFaceColor = Color.white;
bool isProtectionApplied = false;
EntityAlive attackerEntity = world.GetEntity(_attackerEntityId) as EntityAlive;
bool isHoldingDamageItem = false;
if (attackerEntity != null)
{
if (launcherValue == null)
{
launcherValue = attackerEntity.inventory.holdingItemItemValue;
}
isHoldingDamageItem = launcherValue.Equals(attackerEntity.inventory.holdingItemItemValue);
}
bool isHitTargetPlayer = true;
//if hits block or terrain
if (GameUtils.IsBlockOrTerrain(hitInfo.tag))
{
if (ItemAction.ShowDebugDisplayHit)
{
DebugLines.Create(null, attackerEntity.RootTransform, Camera.main.transform.position + Origin.position, hitInfo.hit.pos, new Color(1f, 0.5f, 1f), new Color(1f, 0f, 1f), ItemAction.DebugDisplayHitSize * 2f, ItemAction.DebugDisplayHitSize, ItemAction.DebugDisplayHitTime);
}
ChunkCluster hittedChunk = world.ChunkClusters[hitInfo.hit.clrIdx];
if (hittedChunk == null)
{
return;
}
Vector3i hitBlockPos = hitInfo.hit.blockPos;
BlockValue hitBlockValue = hittedChunk.GetBlock(hitBlockPos);
if (hitBlockValue.isair && hitInfo.hit.blockValue.Block.IsDistantDecoration && hitInfo.hit.blockValue.damage >= hitInfo.hit.blockValue.Block.MaxDamage - 1)
{
hitBlockValue = hitInfo.hit.blockValue;
world.SetBlockRPC(hitBlockPos, hitBlockValue);
}
Block hitBlock = hitBlockValue.Block;
if (hitBlock == null)
{
return;
}
if (hitBlockValue.ischild)
{
hitBlockPos = hitBlock.multiBlockPos.GetParentPos(hitBlockPos, hitBlockValue);
hitBlockValue = hittedChunk.GetBlock(hitBlockPos);
hitBlock = hitBlockValue.Block;
if (hitBlock == null)
{
return;
}
}
if (hitBlockValue.isair)
{
return;
}
float landProtectionModifier = 0;
if (!world.IsWithinTraderArea(hitInfo.hit.blockPos) && hitBlock.blockMaterial.id != "Mbedrock")
{
landProtectionModifier = world.GetLandProtectionHardnessModifier(hitInfo.hit.blockPos, attackerEntity, world.GetGameManager().GetPersistentLocalPlayer());
}
if (landProtectionModifier != 1f)
{
if (attackerEntity && _attackMode != ItemActionAttack.EnumAttackMode.Simulate && attackerEntity is EntityPlayer && !launcherValue.ItemClass.ignoreKeystoneSound && !launcherValue.ToBlockValue().Block.IgnoreKeystoneOverlay)
{
attackerEntity.PlayOneShot("keystone_impact_overlay", false);
}
if (landProtectionModifier < 1f)
{
isProtectionApplied = true;
}
}
if (hitBlockPos != _attackDetails.hitPosition || landProtectionModifier != _attackDetails.hardnessScale || hitBlockValue.type != _attackDetails.blockBeingDamaged.type || (isHoldingDamageItem && projectileValue.SelectedAmmoTypeIndex != _attackDetails.ammoIndex))
{
float finalHardness = Mathf.Max(hitBlock.GetHardness(), 0.1f) * landProtectionModifier;
float finalBlockDamage = _blockDamage * ((_damageMultiplier != null) ? _damageMultiplier.Get(hitBlock.blockMaterial.DamageCategory) : 1f);
if (attackerEntity)
{
finalBlockDamage *= attackerEntity.GetBlockDamageScale();
}
if (_toolBonuses != null && _toolBonuses.Count > 0)
{
finalBlockDamage *= calculateHarvestToolDamageBonus(_toolBonuses, hitBlock.itemsToDrop);
_attackDetails.bHarvestTool = true;
}
_attackDetails.damagePerHit = isProtectionApplied ? 0f : (finalBlockDamage / finalHardness);
_attackDetails.damage = 0f;
_attackDetails.hardnessScale = landProtectionModifier;
_attackDetails.hitPosition = hitBlockPos;
_attackDetails.blockBeingDamaged = hitBlockValue;
if (isHoldingDamageItem)
{
_attackDetails.ammoIndex = projectileValue.SelectedAmmoTypeIndex;
}
}
_attackDetails.raycastHitPosition = hitInfo.hit.blockPos;
Block fmcHitBlock = hitInfo.fmcHit.blockValue.Block;
lightValueAtBlockPos = world.GetLightBrightness(hitInfo.fmcHit.blockPos);
blockFaceColor = fmcHitBlock.GetColorForSide(hitInfo.fmcHit.blockValue, hitInfo.fmcHit.blockFace);
blockFaceParticle = fmcHitBlock.GetParticleForSide(hitInfo.fmcHit.blockValue, hitInfo.fmcHit.blockFace);
MaterialBlock materialForSide = fmcHitBlock.GetMaterialForSide(hitInfo.fmcHit.blockValue, hitInfo.fmcHit.blockFace);
surfaceCategory = materialForSide.SurfaceCategory;
float modifiedBlockDamage = _attackDetails.damagePerHit * _staminaDamageMultiplier;
if (attackerEntity)
{
string blockFaceDamageCategory = materialForSide.DamageCategory ?? string.Empty;
modifiedBlockDamage = (int)MultiActionReversePatches.ProjectileGetValue(PassiveEffects.DamageModifier, projectileValue, modifiedBlockDamage, attackerEntity, null, FastTags<TagGroup.Global>.Parse(blockFaceDamageCategory) | _attackDetails.WeaponTypeTag | hitInfo.fmcHit.blockValue.Block.Tags, true, false);
}
modifiedBlockDamage = ItemActionAttack.DegradationModifier(modifiedBlockDamage, _weaponCondition);
modifiedBlockDamage = isProtectionApplied ? 0f : Utils.FastMax(1f, modifiedBlockDamage);
_attackDetails.damage += modifiedBlockDamage;
_attackDetails.bKilled = false;
_attackDetails.damageTotalOfTarget = hitBlockValue.damage + _attackDetails.damage;
if (_attackDetails.damage > 0f)
{
BlockFace blockFaceFromHitInfo = GameUtils.GetBlockFaceFromHitInfo(hitBlockPos, hitBlockValue, hitInfo.hitCollider, hitInfo.hitTriangleIdx, out _, out _);
int blockFaceTexture = hittedChunk.GetBlockFaceTexture(hitBlockPos, blockFaceFromHitInfo);
int blockCurDamage = hitBlockValue.damage;
bool isBlockBroken = blockCurDamage >= hitBlock.MaxDamage;
int ownerAttackerID = ((ownedEntityId != -1 && ownedEntityId != -2) ? ownedEntityId : _attackerEntityId);
int blockNextDamage = (_attackMode != ItemActionAttack.EnumAttackMode.Simulate) ? hitBlock.DamageBlock(world, hittedChunk.ClusterIdx, hitBlockPos, hitBlockValue, (int)_attackDetails.damage, ownerAttackerID, _attackDetails, _attackDetails.bHarvestTool, false) : 0;
if (blockNextDamage == 0)
{
_attackDetails.damage = 0f;
}
else
{
_attackDetails.damage -= blockNextDamage - blockCurDamage;
}
if (_attackMode != ItemActionAttack.EnumAttackMode.Simulate && canHarvest && attackerEntity is EntityPlayerLocal && blockFaceTexture > 0 && hitBlock.MeshIndex == 0 && blockNextDamage >= hitBlock.MaxDamage * 1f)
{
ParticleEffect particleEffect = new ParticleEffect("paint_block", hitInfo.fmcHit.pos - Origin.position, Utils.BlockFaceToRotation(hitInfo.fmcHit.blockFace), lightValueAtBlockPos, blockFaceColor, null, null)
{
opqueTextureId = BlockTextureData.list[blockFaceTexture].TextureID
};
GameManager.Instance.SpawnParticleEffectClient(particleEffect, _attackerEntityId, false, false);
}
_attackDetails.damageGiven = ((!isBlockBroken) ? (blockNextDamage - blockCurDamage) : 0);
_attackDetails.damageMax = hitBlock.MaxDamage;
_attackDetails.bKilled = !isBlockBroken && blockNextDamage >= hitBlock.MaxDamage;
_attackDetails.itemsToDrop = hitBlock.itemsToDrop;
_attackDetails.bBlockHit = true;
_attackDetails.materialCategory = hitBlock.blockMaterial.SurfaceCategory;
if (attackerEntity != null && _attackMode != ItemActionAttack.EnumAttackMode.Simulate)
{
attackerEntity.MinEventContext.BlockValue = hitBlockValue;
attackerEntity.MinEventContext.Tags = hitBlock.Tags;
if (_attackDetails.bKilled)
{
attackerEntity.FireEvent(MinEventTypes.onSelfDestroyedBlock, isHoldingDamageItem);
attackerEntity.NotifyDestroyedBlock(_attackDetails);
}
else
{
attackerEntity.FireEvent(MinEventTypes.onSelfDamagedBlock, isHoldingDamageItem);
}
}
}
}
else if (hitInfo.tag.StartsWith("E_"))
{
Entity hitEntity = ItemActionAttack.FindHitEntityNoTagCheck(hitInfo, out string hitBodyPart);
if (hitEntity == null)
{
return;
}
if (hitEntity.entityId == _attackerEntityId)
{
return;
}
if (!hitEntity.CanDamageEntity(_attackerEntityId))
{
return;
}
EntityAlive hitEntityAlive = hitEntity as EntityAlive;
DamageSourceEntity damageSourceEntity = new DamageSourceEntity(EnumDamageSource.External, _damageType, _attackerEntityId, hitInfo.ray.direction, hitInfo.transform.name, hitInfo.hit.pos, Voxel.phyxRaycastHit.textureCoord);
damageSourceEntity.AttackingItem = projectileValue;
damageSourceEntity.DismemberChance = _dismemberChance;
damageSourceEntity.CreatorEntityId = ownedEntityId;
bool isCriticalHit = _attackDetails.isCriticalHit;
int finalEntityDamage = (int)_entityDamage;
if (attackerEntity != null && hitEntityAlive != null)
{
FastTags<TagGroup.Global> equipmentTags = FastTags<TagGroup.Global>.none;
if (hitEntityAlive.Health > 0)
{
equipmentTags = FastTags<TagGroup.Global>.Parse(damageSourceEntity.GetEntityDamageEquipmentSlotGroup(hitEntityAlive).ToStringCached());
equipmentTags |= DamagePatches.GetBodyPartTags(damageSourceEntity.GetEntityDamageBodyPart(hitEntityAlive));
}
finalEntityDamage = (int)MultiActionReversePatches.ProjectileGetValue(PassiveEffects.DamageModifier, projectileValue, finalEntityDamage, attackerEntity, null, equipmentTags | _attackDetails.WeaponTypeTag | hitEntityAlive.EntityClass.Tags, true, false);
finalEntityDamage = (int)MultiActionReversePatches.ProjectileGetValue(PassiveEffects.InternalDamageModifier, projectileValue, finalEntityDamage, hitEntityAlive, null, equipmentTags | projectileValue.ItemClass.ItemTags, true, false);
}
if (!hitEntityAlive || hitEntityAlive.Health > 0)
{
finalEntityDamage = Utils.FastMax(1, ItemActionAttack.difficultyModifier(finalEntityDamage, world.GetEntity(_attackerEntityId), hitEntity));
}
else if (_toolBonuses != null)
{
finalEntityDamage = (int)(finalEntityDamage * calculateHarvestToolDamageBonus(_toolBonuses, EntityClass.list[hitEntity.entityClass].itemsToDrop));
}
//Log.Out("Final entity damage: " + finalEntityDamage);
bool isAlreadyDead = hitEntity.IsDead();
int deathHealth = (hitEntityAlive != null) ? hitEntityAlive.DeathHealth : 0;
if (_attackMode != ItemActionAttack.EnumAttackMode.Simulate)
{
if (attackerEntity != null)
{
MinEventParams minEventContext = attackerEntity.MinEventContext;
minEventContext.Other = hitEntityAlive;
minEventContext.StartPosition = hitInfo.ray.origin;
}
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer && (attackerEntity as EntityPlayer == null || !attackerEntity.isEntityRemote) && hitEntity.isEntityRemote && rangeCheckedAction != null)
{
EntityPlayer hitPlayer = hitEntity as EntityPlayer;
if (hitPlayer != null)
{
isHitTargetPlayer = false;
Ray lookRay = attackerEntity.GetLookRay();
lookRay.origin -= lookRay.direction * 0.15f;
float range = Utils.FastMax(rangeCheckedAction.Range, rangeCheckedAction.BlockRange) * ItemActionAttack.attackRangeMultiplier;
string hitTransformPath = null;
List<string> list_buffs = _buffActions;
if (list_buffs != null)
{
if (hitEntityAlive)
{
hitTransformPath = (hitBodyPart != null) ? GameUtils.GetChildTransformPath(hitEntity.transform, hitInfo.transform) : null;
}
else
{
list_buffs = null;
}
}
if (attackerEntity != null)
{
attackerEntity.FireEvent(MinEventTypes.onSelfAttackedOther, isHoldingDamageItem);
if (hitEntityAlive != null && hitEntityAlive.RecordedDamage.Strength > 0)
{
attackerEntity.FireEvent(MinEventTypes.onSelfDamagedOther, isHoldingDamageItem);
}
}
if (!isAlreadyDead && hitEntity.IsDead() && attackerEntity != null)
{
attackerEntity.FireEvent(MinEventTypes.onSelfKilledOther, isHoldingDamageItem);
}
if (hitEntityAlive && hitEntityAlive.RecordedDamage.ArmorDamage > hitEntityAlive.RecordedDamage.Strength)
{
surfaceCategory = "metal";
}
else
{
surfaceCategory = EntityClass.list[hitEntity.entityClass].Properties.Values["SurfaceCategory"];
}
blockFaceParticle = surfaceCategory;
lightValueAtBlockPos = hitEntity.GetLightBrightness();
string hitParticle = string.Format("impact_{0}_on_{1}", _attackingDeviceMadeOf, blockFaceParticle);
string hitSound = (surfaceCategory != null) ? string.Format("{0}hit{1}", _attackingDeviceMadeOf, surfaceCategory) : null;
if (_hitSoundOverrides != null && _hitSoundOverrides.ContainsKey(surfaceCategory))
{
hitSound = _hitSoundOverrides[surfaceCategory];
}
ParticleEffect particleEffect2 = new ParticleEffect(hitParticle, hitInfo.fmcHit.pos, Utils.BlockFaceToRotation(hitInfo.fmcHit.blockFace), lightValueAtBlockPos, blockFaceColor, hitSound, null);
hitPlayer.ServerNetSendRangeCheckedDamage(lookRay.origin, range, damageSourceEntity, finalEntityDamage, isCriticalHit, list_buffs, hitTransformPath, particleEffect2);
}
}
if (isHitTargetPlayer)
{
int damageDealt = hitEntity.DamageEntity(damageSourceEntity, finalEntityDamage, isCriticalHit, 1f);
if (damageDealt != -1 && attackerEntity)
{
MinEventParams attackerMinEventParams = attackerEntity.MinEventContext;
attackerMinEventParams.Other = hitEntityAlive;
attackerMinEventParams.StartPosition = hitInfo.ray.origin;
if (ownedEntityId != -1)
{
launcherValue.FireEvent(MinEventTypes.onSelfAttackedOther, attackerEntity.MinEventContext);
}
attackerEntity.FireEvent(MinEventTypes.onSelfAttackedOther, isHoldingDamageItem);
if (hitEntityAlive && hitEntityAlive.RecordedDamage.Strength > 0)
{
attackerEntity.FireEvent(MinEventTypes.onSelfDamagedOther, isHoldingDamageItem);
}
}
if (!isAlreadyDead && hitEntity.IsDead() && attackerEntity)
{
attackerEntity.FireEvent(MinEventTypes.onSelfKilledOther, isHoldingDamageItem);
}
if (damageDealt != -1 && hitEntityAlive && _buffActions != null && _buffActions.Count > 0)
{
for (int i = 0; i < _buffActions.Count; i++)
{
BuffClass buff = BuffManager.GetBuff(_buffActions[i]);
if (buff != null)
{
float bufProcChance = MultiActionReversePatches.ProjectileGetValue(PassiveEffects.BuffProcChance, null, 1f, attackerEntity, null, FastTags<TagGroup.Global>.Parse(buff.Name), true, false);
if (hitEntityAlive.rand.RandomFloat <= bufProcChance)
{
hitEntityAlive.Buffs.AddBuff(_buffActions[i], attackerEntity.entityId, true, false, -1f);
}
}
}
}
}
}
if (hitEntityAlive && hitEntityAlive.RecordedDamage.ArmorDamage > hitEntityAlive.RecordedDamage.Strength)
{
surfaceCategory = "metal";
}
else
{
surfaceCategory = EntityClass.list[hitEntity.entityClass].Properties.Values["SurfaceCategory"];
}
blockFaceParticle = surfaceCategory;
lightValueAtBlockPos = hitEntity.GetLightBrightness();
EntityPlayer attackerPlayer = attackerEntity as EntityPlayer;
if (attackerPlayer)
{
if (isAlreadyDead && hitEntity.IsDead() && hitEntityAlive && hitEntityAlive.DeathHealth + finalEntityDamage > -1 * EntityClass.list[hitEntity.entityClass].DeadBodyHitPoints)
{
_attackDetails.damageTotalOfTarget = (float)(-1 * hitEntityAlive.DeathHealth);
_attackDetails.damageGiven = deathHealth + 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 (!isAlreadyDead && (hitEntityAlive.IsDead() || hitEntityAlive.Health <= 0) && EntityClass.list.ContainsKey(hitEntity.entityClass))
{
if ((_flags & 2) > 0)
{
float trapXP = MultiActionReversePatches.ProjectileGetValue(PassiveEffects.ElectricalTrapXP, attackerPlayer.inventory.holdingItemItemValue, 0f, attackerPlayer, null, default, true, false);
if (trapXP > 0f)
{
attackerPlayer.AddKillXP(hitEntityAlive, trapXP);
}
}
else
{
attackerPlayer.AddKillXP(hitEntityAlive, 1f);
}
}
}
if (hitEntity is EntityDrone)
{
_attackDetails.entityHit = hitEntity;
}
}
if ((_flags & 8) > 0)
{
canHarvest = false;
}
if (isHitTargetPlayer && _attackMode != ItemActionAttack.EnumAttackMode.Simulate && canHarvest && blockFaceParticle != null && ((_attackDetails.bBlockHit && !_attackDetails.bKilled) || !_attackDetails.bBlockHit))
{
string hitParticle = string.Format("impact_{0}_on_{1}", _attackingDeviceMadeOf, blockFaceParticle);
if (_attackMode == ItemActionAttack.EnumAttackMode.RealAndHarvesting && (_flags & 4) > 0 && ParticleEffect.IsAvailable(hitParticle + "_harvest"))
{
hitParticle += "_harvest";
}
string hitSound = (surfaceCategory != null) ? string.Format("{0}hit{1}", _attackingDeviceMadeOf, surfaceCategory) : null;
if (_hitSoundOverrides != null && _hitSoundOverrides.ContainsKey(surfaceCategory))
{
hitSound = _hitSoundOverrides[surfaceCategory];
}
world.GetGameManager().SpawnParticleEffectServer(new ParticleEffect(hitParticle, hitInfo.fmcHit.pos, Utils.BlockFaceToRotation(hitInfo.fmcHit.blockFace), lightValueAtBlockPos, blockFaceColor, hitSound, null), _attackerEntityId, false, true);
}
if ((_flags & 1) > 0 && attackerEntity != null && attackerEntity.inventory != null)
{
attackerEntity.inventory.CallOnToolbeltChangedInternal();
}
}
private 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;
}
public static float GetProjectileDamageBlock(this ItemActionAttack self, ItemValue _itemValue, BlockValue _blockValue, EntityAlive _holdingEntity = null, int actionIndex = 0)
{
FastTags<TagGroup.Global> tmpTag = ((actionIndex != 1) ? ItemActionAttack.PrimaryTag : ItemActionAttack.SecondaryTag);
ItemClass launcherClass = ItemClass.GetForId(_itemValue.Meta);
tmpTag |= ((launcherClass == null) ? ItemActionAttack.MeleeTag : launcherClass.ItemTags);
if (_holdingEntity != null)
{
tmpTag |= _holdingEntity.CurrentStanceTag | _holdingEntity.CurrentMovementTag;
}
tmpTag |= _blockValue.Block.Tags;
float value = MultiActionReversePatches.ProjectileGetValue(PassiveEffects.BlockDamage, _itemValue, self.damageBlock, _holdingEntity, null, tmpTag, true, false)/* * GetProjectileBlockDamagePerc(_itemValue, _holdingEntity)*/;
//Log.Out($"block damage {value} base damage {self.GetBaseDamageBlock(null)} action index {actionIndex} launcher {launcherClass.Name} projectile {_itemValue.ItemClass.Name}");
return value;
}
public static float GetProjectileDamageEntity(this ItemActionAttack self, ItemValue _itemValue, EntityAlive _holdingEntity = null, int actionIndex = 0)
{
FastTags<TagGroup.Global> tmpTag = ((actionIndex != 1) ? ItemActionAttack.PrimaryTag : ItemActionAttack.SecondaryTag);
ItemClass launcherClass = ItemClass.GetForId(_itemValue.Meta);
tmpTag |= ((launcherClass == null) ? ItemActionAttack.MeleeTag : launcherClass.ItemTags);
if (_holdingEntity != null)
{
tmpTag |= _holdingEntity.CurrentStanceTag | _holdingEntity.CurrentMovementTag;
}
var res = MultiActionReversePatches.ProjectileGetValue(PassiveEffects.EntityDamage, _itemValue, self.damageEntity, _holdingEntity, null, tmpTag, true, false)/* * GetProjectileEntityDamagePerc(_itemValue, _holdingEntity)*/;
#if DEBUG
Log.Out($"get projectile damage entity for action index {actionIndex}, item {launcherClass.Name}, result {res}");
#endif
return res;
}
//public static float GetProjectileBlockDamagePerc(ItemValue _itemValue, EntityAlive _holdingEntity)
//{
// float value = MultiActionReversePatches.ProjectileGetValue(CustomEnums.ProjectileImpactDamagePercentBlock, _itemValue, 1, _holdingEntity, null);
// //Log.Out("Block damage perc: " + value);
// return value;
//}
//public static float GetProjectileEntityDamagePerc(ItemValue _itemValue, EntityAlive _holdingEntity)
//{
// float value = MultiActionReversePatches.ProjectileGetValue(CustomEnums.ProjectileImpactDamagePercentEntity, _itemValue, 1, _holdingEntity, null);
// //Log.Out("Entity damage perc: " + value);
// return value;
//}
public static void ProjectileValueModifyValue(this ItemValue _projectileItemValue, EntityAlive _entity, ItemValue _originalItemValue, PassiveEffects _passiveEffect, ref float _originalValue, ref float _perc_value, FastTags<TagGroup.Global> _tags, bool _useMods = true, bool _useDurability = false)
{
if (_originalItemValue != null)
{
Log.Warning($"original item value present: item {_originalItemValue.ItemClass.Name}");
return;
}
int seed = MinEventParams.CachedEventParam.Seed;
if (_entity != null)
{
seed = _entity.MinEventContext.Seed;
}
ItemClass launcherClass = ItemClass.GetForId(_projectileItemValue.Meta);
int actionIndex = _projectileItemValue.SelectedAmmoTypeIndex;
if (launcherClass != null)
{
if (launcherClass.Actions != null && launcherClass.Actions.Length != 0 && launcherClass.Actions[actionIndex] is ItemActionRanged)
{
ItemClass ammoClass = _projectileItemValue.ItemClass;
if (ammoClass != null && ammoClass.Effects != null)
{
ammoClass.Effects.ModifyValue(_entity, _passiveEffect, ref _originalValue, ref _perc_value, 0f, _tags);
}
}
if (launcherClass.Effects != null)
{
MinEventParams.CachedEventParam.Seed = (int)_projectileItemValue.Seed + (int)((_projectileItemValue.Seed != 0) ? _passiveEffect : PassiveEffects.None);
if (_entity != null)
{
_entity.MinEventContext.Seed = MinEventParams.CachedEventParam.Seed;
}
float prevOriginal = _originalValue;
launcherClass.Effects.ModifyValue(_entity, _passiveEffect, ref _originalValue, ref _perc_value, _projectileItemValue.Quality, _tags);
if (_useDurability)
{
float percentUsesLeft = _projectileItemValue.PercentUsesLeft;
switch (_passiveEffect)
{
case PassiveEffects.PhysicalDamageResist:
if (percentUsesLeft < 0.5f)
{
float diff = _originalValue - prevOriginal;
_originalValue = prevOriginal + diff * percentUsesLeft * 2f;
}
break;
case PassiveEffects.ElementalDamageResist:
if (percentUsesLeft < 0.5f)
{
float diff = _originalValue - prevOriginal;
_originalValue = prevOriginal + diff * percentUsesLeft * 2f;
}
break;
case PassiveEffects.BuffResistance:
if (percentUsesLeft < 0.5f)
{
float diff = _originalValue - prevOriginal;
_originalValue = prevOriginal + diff * percentUsesLeft * 2f;
}
break;
}
}
}
}
else
{
Log.Warning($"launcher class not found: item id{_projectileItemValue.Meta}");
}
if (_useMods)
{
for (int i = 0; i < _projectileItemValue.CosmeticMods.Length; i++)
{
if (_projectileItemValue.CosmeticMods[i] != null && _projectileItemValue.CosmeticMods[i].ItemClass is ItemClassModifier && !MultiActionManager.ShouldExcludePassive(_projectileItemValue.type, _projectileItemValue.CosmeticMods[i].type, actionIndex))
{
_projectileItemValue.CosmeticMods[i].ModifyValue(_entity, _projectileItemValue, _passiveEffect, ref _originalValue, ref _perc_value, _tags);
}
}
for (int i = 0; i < _projectileItemValue.Modifications.Length; i++)
{
if (_projectileItemValue.Modifications[i] != null && _projectileItemValue.Modifications[i].ItemClass is ItemClassModifier && !MultiActionManager.ShouldExcludePassive(_projectileItemValue.type, _projectileItemValue.Modifications[i].type, actionIndex))
{
_projectileItemValue.Modifications[i].ModifyValue(_entity, _projectileItemValue, _passiveEffect, ref _originalValue, ref _perc_value, _tags);
}
}
}
}
}
}