话不多说丢源码,有兴趣的作者可以自行修改,比如改成指定刷新的entityGroup,或者其他Entity刷新时。
using Harmony;
using System.Collections.Generic;
using UnityEngine;
using UniLinq;
using DMT;
using System.Reflection;
public class AirdropSpawnZeds
{
// 此函数不用管,加载入内核的
public class AirdropSpawnZeds_Init : IHarmony
{
public void Start()
{
Debug.Log(” Loading Patch : ” + GetType().ToString());
var harmony = HarmonyInstance.Create(GetType().ToString());
harmony.PatchAll(Assembly.GetExecutingAssembly());
}
}
// 当空投的Entity刷新时执行
[HarmonyPatch(typeof(EntitySupplyCrate))]
[HarmonyPatch(“OnUpdateEntity”)]
class PatchEntitySupplyCrateOnUpdateEntity
{
static bool Prefix(EntitySupplyCrate __instance)
{
// 判断包为空则销毁,这个是系统源代码的,这里只是复制黏贴了一下
if (__instance.lootContainer != null && __instance.lootContainer.bTouched && __instance.lootContainer.IsEmpty() && !__instance.bDead)
{
__instance.bDead = true;
__instance.Health = 0;
return true;
}
// 判断包的名字是否叫空投,是否在地上,通过里面的食物计数判断当前最大僵尸量
if (__instance.EntityName == “sc_General” && __instance.onGround && __instance.classMaxFood < GetMaxZombies() && (__instance.lootContainer == null || (__instance.lootContainer != null && !__instance.lootContainer.bTouched)))
{
var spawnRadius = 30f;
// 是否正在血月,如果是的话就算了,血月还在野外捡空投不容易
if (__instance.IsBloodMoon)
{
var closestplayerStill = __instance.world.GetClosestPlayer(__instance, spawnRadius, false);
if (closestplayerStill == null)
{
__instance.IsBloodMoon = false;
}
else
return true;
}
// 离空投最近的玩家
var closestplayer = __instance.world.GetClosestPlayer(__instance, 5f, false);
if (closestplayer == null)
return true;
// 判断附近有没有位置给僵尸刷新,空投掉海里了就算了
BiomeSpawnEntityGroupList biomeSpawnEntityGroupList = BiomeSpawningClass.list[“airdrop”];
if (biomeSpawnEntityGroupList == null)
return true;
__instance.IsBloodMoon = true;
// 计算并取附近所有玩家中最大的游戏阶段
int partyLevel = GetGamestageFromBounds(__instance.position.x, __instance.position.y, __instance.position.z, “Airdrop”);
// 根据附近的环境查找生成的EntityGroup,比如废墟晚上,绿地白天的group
int matchingGameStage = 0;
List<BiomeSpawnEntityGroupData> list = new List<BiomeSpawnEntityGroupData>();
EDaytime edaytime = (!__instance.world.IsDaytime()) ? EDaytime.Night : EDaytime.Day;
foreach (var x in biomeSpawnEntityGroupList.list.AsEnumerable().Reverse())
{
if (matchingGameStage == 0 && x.gameStage <= partyLevel)
matchingGameStage = x.gameStage;
if (matchingGameStage > 0)
{
if (x.gameStage != matchingGameStage || x.entityGroupRefName.Contains(“Animals”) || x.entityGroupRefName.Contains(“Bandit”)) break;
if (x.daytime == EDaytime.Any || x.daytime == edaytime)
list.Add(x);
}
}
// 反转列表方便取表头
list.Reverse();
// 随机半径生成随机Id的Entity
System.Random rnd = new System.Random();
var spawnGroup = list.First();
var group = EntityGroups.list[spawnGroup.entityGroupRefName];
var rndEntityId = new System.Random();
for (int i = 0; i < (spawnGroup.maxCount); i++)
{
// 在空投的坐标系下随机15m的半径生成僵尸
var randomPosition = __instance.GetPosition();
randomPosition.x = randomPosition.x + rnd.Next(-(int)spawnRadius / 2, (int)spawnRadius / 2);
randomPosition.z = randomPosition.z + rnd.Next(-(int)spawnRadius / 2, (int)spawnRadius / 2);
randomPosition.y = 0;
// 随机坐标中y是当前的高度,生成的僵尸不能在地下埋着,所以计算当前xz坐标下的物块的高度来获取y
var blockPos = World.worldToBlockPos(randomPosition);
var chunk = (Chunk)__instance.world.GetChunkFromWorldPos(blockPos);
blockPos.y = (chunk.GetHeight(World.toBlockXZ((int)randomPosition.x), World.toBlockXZ((int)randomPosition.z)) + 1);
randomPosition.y = (float)blockPos.y;
Entity entityEnemy = EntityFactory.CreateEntity(group[rndEntityId.Next(group.Count – 1)].entityClassId, randomPosition);
GameManager.Instance.World.SpawnEntityInWorld(entityEnemy);
entityEnemy.SetSpawnerSource(EnumSpawnerSource.Dynamic);
// 通过最大食物来判断是否生成的僵尸太多了
__instance.classMaxFood++;
// 多了的话就别生成了,小伙子舔个空投不容易
if (__instance.classMaxFood >= GetMaxZombies())
return true;
}
}
return true;
}
// 计算并取附近所有玩家中最大的游戏阶段
public static int GetGamestageFromBounds(float x, float y, float z, string source, bool log = false)
{
// 物块的点坐标
var chunkPosition = new Vector3(x, y, z);
// 在物块坐标范围200的区域内创建包围盒
var bounds = new Bounds(new Vector3(chunkPosition.x, chunkPosition.y, chunkPosition.z), new Vector3(200f, 200f, 200f));
// 判断包围盒内有多少个玩家,取出每个玩家的游戏阶段
List<Entity> playersInBounds = GameManager.Instance.World.GetEntitiesInBounds(typeof(EntityPlayer), bounds, new List<Entity>());
List<int> partyLevelList = new List<int>();
foreach (var entityBound in playersInBounds)
{
var player = entityBound as EntityPlayer;
partyLevelList.Add(player.gameStage);
}
// 取所有玩家中最大的游戏阶段
return Mathf.Max(GameStageDefinition.CalcPartyLevel(partyLevelList), 1);
}
// 获取最大僵尸数,如果最大僵尸数大于100,则取100
private static int GetMaxZombies()
{
return GamePrefs.GetInt(EnumGamePrefs.MaxSpawnedZombies) > 100 ? 100 : GamePrefs.GetInt(EnumGamePrefs.MaxSpawnedZombies);
}
}
}