Files
zzz_REBIRTH__Utils/Harmony/Harmony_ProjectileMoveScript.cs
2025-06-04 16:44:53 +09:30

177 lines
13 KiB
C#

namespace Harmony.ProjectileMoveScriptPatches
{
[HarmonyPatch(typeof(ProjectileMoveScript))]
[HarmonyPatch("checkCollision")]
public class checkCollisionPatch
{
public static bool Prefix(ProjectileMoveScript __instance)
{
if (__instance.state != ProjectileMoveScript.State.Active || (UnityEngine.Object)ProjectileMoveScript.gameManager == (UnityEngine.Object)null)
return false;
World world = ProjectileMoveScript.gameManager.World;
if (world == null)
return false;
Vector3 vector3_1 = !__instance.bOnIdealPos ? __instance.idealPosition : __instance.transform.position + Origin.position;
Vector3 vector3_2 = vector3_1 - __instance.previousPosition;
float magnitude = vector3_2.magnitude;
if ((double)magnitude < 0.039999999105930328)
return false;
EntityAlive firingEntity = (EntityAlive)__instance.firingEntity;
Ray ray = new Ray(__instance.previousPosition, vector3_2.normalized);
__instance.waterCollisionParticles.CheckCollision(ray.origin, ray.direction, magnitude, (UnityEngine.Object)firingEntity != (UnityEngine.Object)null ? firingEntity.entityId : -1);
int _layerId = -1;
if ((UnityEngine.Object)firingEntity != (UnityEngine.Object)null && (UnityEngine.Object)firingEntity.emodel != (UnityEngine.Object)null)
{
_layerId = firingEntity.GetModelLayer();
firingEntity.SetModelLayer(2);
}
int _hitMask = __instance.hmOverride == 0 ? 80 : __instance.hmOverride;
int num1 = Voxel.Raycast(world, ray, magnitude, -538750997, _hitMask, __instance.radius) ? 1 : 0;
if (_layerId >= 0)
firingEntity.SetModelLayer(_layerId);
if (num1 != 0 && (GameUtils.IsBlockOrTerrain(Voxel.voxelRayHitInfo.tag) || Voxel.voxelRayHitInfo.tag.StartsWith("E_")))
{
if ((UnityEngine.Object)__instance.firingEntity != (UnityEngine.Object)null && !__instance.firingEntity.isEntityRemote)
{
firingEntity.MinEventContext.Other = ItemActionAttack.FindHitEntity(Voxel.voxelRayHitInfo) as EntityAlive;
ItemActionAttack.AttackHitInfo _attackDetails = new ItemActionAttack.AttackHitInfo()
{
WeaponTypeTag = ItemActionAttack.RangedTag
};
ItemActionAttack.Hit(Voxel.voxelRayHitInfo, __instance.ProjectileOwnerID, EnumDamageTypes.Piercing, Mathf.Lerp(1f, __instance.itemActionProjectile.GetDamageBlock(__instance.itemValueLauncher, ItemActionAttack.GetBlockHit(world, Voxel.voxelRayHitInfo), firingEntity), __instance.actionData.strainPercent), Mathf.Lerp(1f, __instance.itemActionProjectile.GetDamageEntity(__instance.itemValueLauncher, firingEntity), __instance.actionData.strainPercent), 1f, 1f, EffectManager.GetValue(PassiveEffects.CriticalChance, __instance.itemValueLauncher, __instance.itemProjectile.CritChance.Value, firingEntity, tags: __instance.itemProjectile.ItemTags), ItemAction.GetDismemberChance((ItemActionData)__instance.actionData, Voxel.voxelRayHitInfo), __instance.itemProjectile.MadeOfMaterial.SurfaceCategory, __instance.itemActionProjectile.GetDamageMultiplier(), __instance.getBuffActions(), _attackDetails, _actionExp: __instance.itemActionProjectile.ActionExp, _actionExpBonus: __instance.itemActionProjectile.ActionExpBonusMultiplier, damagingItemValue: __instance.itemValueLauncher);
if ((UnityEngine.Object)firingEntity.MinEventContext.Other == (UnityEngine.Object)null)
firingEntity.FireEvent(MinEventTypes.onSelfPrimaryActionMissEntity);
firingEntity.FireEvent(MinEventTypes.onProjectileImpact, false);
MinEventParams.CachedEventParam.Self = firingEntity;
MinEventParams.CachedEventParam.Position = Voxel.voxelRayHitInfo.hit.pos;
MinEventParams.CachedEventParam.ItemValue = __instance.itemValueProjectile;
MinEventParams.CachedEventParam.Other = firingEntity.MinEventContext.Other;
__instance.itemProjectile.FireEvent(MinEventTypes.onProjectileImpact, MinEventParams.CachedEventParam);
if (__instance.itemActionProjectile.Explosion.ParticleIndex > 0)
{
Vector3 hitPos = Voxel.voxelRayHitInfo.hit.pos - vector3_2.normalized * 0.1f;
Vector3i vector3i = World.worldToBlockPos(hitPos);
if (!world.GetBlock(vector3i).isair)
vector3i = Voxel.OneVoxelStep(vector3i, hitPos, -vector3_2.normalized, out hitPos, out BlockFace _);
ProjectileMoveScript.gameManager.ExplosionServer(Voxel.voxelRayHitInfo.hit.clrIdx, hitPos, vector3i, Quaternion.identity, __instance.itemActionProjectile.Explosion, __instance.ProjectileOwnerID, 0.0f, false, __instance.itemValueLauncher);
__instance.SetState(ProjectileMoveScript.State.Dead);
return false;
}
if (__instance.itemProjectile.IsSticky)
{
GameRandom gameRandom = world.GetGameRandom();
ProgressionValue progressionValue = firingEntity.Progression.GetProgressionValue("FuriousRamsayPerkBows");
int progressionLevel = 1;
if (!RebirthUtilities.ScenarioSkip() && progressionValue != null)
{
progressionLevel = progressionValue.Level;
}
float baseStickChance = 0f;
float addedChance = 0f;
float stickChance;
bool isArrow = __instance.itemProjectile.Name.ToLower().Contains("ammoarrow") ||
__instance.itemProjectile.Name.ToLower().Contains("ammocrossbowbolt");
if (!isArrow)
{
stickChance = EffectManager.GetValue(PassiveEffects.ProjectileStickChance, __instance.itemValueLauncher, 0.5f, firingEntity, tags: __instance.itemProjectile.ItemTags);
}
else
{
if (__instance.itemProjectile.Name.ToLower().Contains("stone"))
{
baseStickChance = 0.3f;
addedChance = progressionLevel / 25f;
//Log.Out("ProjectileMoveScriptPatches-checkCollision STONE, addedChance: " + addedChance);
stickChance = baseStickChance + addedChance;
}
else if (__instance.itemProjectile.Name.ToLower().Contains("iron"))
{
baseStickChance = 0.4f;
addedChance = progressionLevel / 25f;
//Log.Out("ProjectileMoveScriptPatches-checkCollision IRON, addedChance: " + addedChance);
stickChance = baseStickChance + addedChance;
}
else if (__instance.itemProjectile.Name.ToLower().Contains("steelap"))
{
baseStickChance = 0.5f;
addedChance = progressionLevel / 25f;
//Log.Out("ProjectileMoveScriptPatches-checkCollision STEEL, addedChance: " + addedChance);
stickChance = baseStickChance + addedChance;
}
else
{
//Log.Out("ProjectileMoveScriptPatches-checkCollision OTHER");
stickChance = 0f;
}
}
float random = gameRandom.RandomFloat;
//Log.Out("ProjectileMoveScriptPatches-checkCollision baseStickChance: " + baseStickChance);
//Log.Out("ProjectileMoveScriptPatches-checkCollision addedChance: " + addedChance);
//Log.Out("ProjectileMoveScriptPatches-checkCollision progressionLevel: " + progressionLevel);
//Log.Out("ProjectileMoveScriptPatches-checkCollision stickChance: " + stickChance);
//Log.Out("ProjectileMoveScriptPatches-checkCollision ItemClass.Name: " + __instance.itemValueLauncher.ItemClass.Name);
//Log.Out("ProjectileMoveScriptPatches-checkCollision itemProjectile.Name: " + __instance.itemProjectile.Name);
//Log.Out("ProjectileMoveScriptPatches-checkCollision random: " + random);
if (GameUtils.IsBlockOrTerrain(Voxel.voxelRayHitInfo.tag))
{
double randomFloat = (double)gameRandom.RandomFloat;
ItemValue itemValueLauncher = __instance.itemValueLauncher;
EntityAlive _entity = firingEntity;
FastTags<TagGroup.Global> itemTags = __instance.itemProjectile.ItemTags;
BlockValue blockValue = Voxel.voxelRayHitInfo.fmcHit.blockValue;
FastTags<TagGroup.Global> fastTags = FastTags<TagGroup.Global>.Parse(blockValue.Block.blockMaterial.SurfaceCategory);
FastTags<TagGroup.Global> tags = itemTags | fastTags;
double num2 = (double)EffectManager.GetValue(PassiveEffects.ProjectileStickChance, itemValueLauncher, 0.5f, _entity, tags: tags);
if (randomFloat < num2)
{
__instance.ProjectileID = ProjectileManager.AddProjectileItem(__instance.transform, _position: Voxel.voxelRayHitInfo.hit.pos, _movementLastFrame: vector3_2.normalized, _itemValueType: __instance.itemValueProjectile.type);
__instance.SetState(ProjectileMoveScript.State.Sticky);
}
else
{
GameManager gameManager = ProjectileMoveScript.gameManager;
Vector3 pos = Voxel.voxelRayHitInfo.hit.pos;
Quaternion rotation = Utils.BlockFaceToRotation(Voxel.voxelRayHitInfo.fmcHit.blockFace);
Color white = Color.white;
blockValue = Voxel.voxelRayHitInfo.fmcHit.blockValue;
string _soundName = string.Format("{0}hit{1}", (object)blockValue.Block.blockMaterial.SurfaceCategory, (object)__instance.itemProjectile.MadeOfMaterial.SurfaceCategory);
ParticleEffect _pe = new ParticleEffect("impact_metal_on_wood", pos, rotation, 1f, white, _soundName, (Transform)null);
int entityId = __instance.firingEntity.entityId;
gameManager.SpawnParticleEffectServer(_pe, entityId, false, false);
__instance.SetState(ProjectileMoveScript.State.Dead);
}
}
else if (random < stickChance)
{
__instance.ProjectileID = ProjectileManager.AddProjectileItem(__instance.transform, _position: Voxel.voxelRayHitInfo.hit.pos, _movementLastFrame: vector3_2.normalized, _itemValueType: __instance.itemValueProjectile.type);
Utils.SetLayerRecursively(ProjectileManager.GetProjectile(__instance.ProjectileID).gameObject, 14);
__instance.SetState(ProjectileMoveScript.State.Sticky);
}
else
{
ProjectileMoveScript.gameManager.SpawnParticleEffectServer(new ParticleEffect("impact_metal_on_wood", Voxel.voxelRayHitInfo.hit.pos, Utils.BlockFaceToRotation(Voxel.voxelRayHitInfo.fmcHit.blockFace), 1f, Color.white, "bullethitwood", (Transform)null), __instance.firingEntity.entityId, false, false);
__instance.SetState(ProjectileMoveScript.State.Dead);
}
}
else
__instance.SetState(ProjectileMoveScript.State.Dead);
}
else
__instance.SetState(ProjectileMoveScript.State.Dead);
}
__instance.previousPosition = vector3_1;
return false;
}
}
}