城市:天际线 MOD制作教程 MOD源码解析及开发指南
- 来源:3DM论坛-xxyztwz
- 作者:售梦者
- 编辑:售梦者
三、进阶篇
然后就是我们的hack时间了。这部分没有任何官方说明,出现的bug也只能靠我们自己解决,出现任何奇怪的事情都是正常的。然后我们继续。
要替换官方的BusAI,最简单的方法我相信大家已经猜到了,就是继承官方的AI,然后仅仅修改我们需要修改的部分就好了。那么,我也是这么干的。
看代码:
using ColossalFramework;
using UnityEngine;
namespace SuperBigTransport
{
class BigBusAI : BusAI, IAIReplacement
{
public void CopyFrom(BusAI ai)//我们自己定义的接口,主要用于两个AI的属性对拷
{
m_passengerCapacity = Mod.unit_number * 5;//这里是公交的容量,但是这个数字仅仅是显示用的,实际上,能上多少人不已这里为准。窃以为,这是官方代码的bug
m_ticketPrice = ai.m_ticketPrice;//车票多少钱,这个我没改过,不知道是不是只改这里就是增加车票收入,有兴趣的同学可以试试。
m_info = ai.m_info;//info,就是bus的基本信息,busInfo,前面提到过的,忘了的话自己回去看。但是不管它是什么,拷过来就好了
}
public override bool ArriveAtDestination(ushort vehicleID, ref Vehicle vehicleData)//复写官方的车辆到站后的处理逻辑。官方的方法里,车到站以后有很多的判定步骤,要判断该下多少人,能上多少人,是否是终点站,等等一大堆。我没把握能全部写好,而能上多少人这个方法它又是private的(日),所以,只能改这个,并且最后一步还的调用base的方法。
{
var citizenManager = Singleton
var unitId = vehicleData.m_citizenUnits;//好了,这里涉及到另一件事情,是citizen所特有的概念,citizenUnit,前面的public const int unit_number = 16;就是跟这个相关的。这里呢,每个citizenUnit里面能装5个citizen,一个citizen可以被装在多个citizenUnit里,装的也仅仅是引用。citizenUnit是一个链表结构,citizenUnit有一个属性是nextUnit,就是下一个citizenUnit的引用,如果没有下一个,就是0,说明链表结束。那么这个citizenUnit用在哪里呢?这么说,所有能装人的地方,本质上就是这个citizenUnit有多长的结构。每辆车、每个建筑物,都有一个citizenUnit的引用,指向的是第一个citizenUnit的位置。所以,我们要增容,就是扩展这个citizenUnit。
var cu = citizenManager.m_units.m_buffer[unitId];//这行代码说明,citizenUnit也是由CitizenManager来统一管理的
int i = 1;
while (cu.m_nextUnit>0) {//判一下当前的容量数是多少
i++;
cu = citizenManager.m_units.m_buffer[cu.m_nextUnit];
}
if (i != Mod.unit_number) {//如果不等于预期,就改
uint firstId;
var random = new ColossalFramework.Math.Randomizer();
citizenManager.CreateUnits(out firstId, ref random, 0, vehicleID, 0, 0, 0, Mod.unit_number * 5, 0);//citizenUnit既然是由CitizenManager来统一管理的,那么创建肯定也是由CitizenManager来统一做的。我们简单的在这里创建了一个符合我们预期长度的citizenUnit
vehicleData.m_citizenUnits = firstId;//然后粗暴的直接替换
//citizenManager.ReleaseUnits(unitId);//这里不能释放,释放了市民就找不到路了。释放了有什么效果请自行观察。
}
return base.ArriveAtDestination(vehicleID, ref vehicleData);
}
}
}
好了,这里就是我们增容的核心代码了。那么现在有一个bug,就是公交会闪。在这里我表示我非常的冤枉,跟我真的没啥关系。。。。我没动frame..我只是替换了个数组。
所以,这个替换是非常生硬的,直接的后果就是会导致存档发生变化。即使关闭了mod,也无法改变已经客观存在的链表结构。所以我说嘛。。官方偷懒。。不好好的调用那个容积属性进行判断。。非要搞数组,还是链表结构的。。。真是无语。
然后,上面只是公交车的,下面是地铁和客运火车的。我直接贴代码了,因为结构差不多,我就不解释了。有一个小bug,会导致一个不合理的现象,但是很隐蔽,不知道大家能发现么?
using ColossalFramework;
using System.Collections.Generic;
namespace SuperBigTransport
{
class BigPassengerTrainAI : PassengerTrainAI, IAIReplacement
{
public void CopyFrom(PassengerTrainAI ai)
{
m_passengerCapacity = Mod.unit_number * 5;
m_ticketPrice = ai.m_ticketPrice;
m_info = ai.m_info;
m_arriveEffect = ai.m_arriveEffect;
m_transportInfo = ai.m_transportInfo;
}
CitizenManager citizenManager = Singleton
public override bool ArriveAtDestination(ushort vehicleID, ref Vehicle vehicleData)
{
var unitId = vehicleData.m_citizenUnits;
var cu = citizenManager.m_units.m_buffer[unitId];
int i = 1;
while (cu.m_nextUnit > 0)
{
i++;
cu = citizenManager.m_units.m_buffer[cu.m_nextUnit];
}
uint firstId;
int n;
if (i < Mod.unit_number)
{
var random = new ColossalFramework.Math.Randomizer();
if (vehicleData.m_transferType==39)//metro
{
n = (Mod.unit_number-i) * 5*6 + 30;
citizenManager.CreateUnits(out firstId, ref random, 0, vehicleData.GetFirstVehicle(vehicleID), 0, 0, 0, n, 0);
}else
{
n = (Mod.unit_number-i) * 5 *8 + 30;
citizenManager.CreateUnits(out firstId, ref random, 0, vehicleData.GetFirstVehicle(vehicleID), 0, 0, 0, n, 0);
}
vehicleData.m_citizenUnits = firstId;
//citizenManager.ReleaseUnits(unitId);
}
else if (i > Mod.unit_number)
{
var random = new ColossalFramework.Math.Randomizer();
if (vehicleData.m_transferType == 39)//metro
{
firstId = citizenManager.m_units.m_buffer[unitId].m_nextUnit;
citizenManager.ReleaseUnits(unitId);
vehicleData.m_citizenUnits = firstId;
n = (Mod.unit_number - 6) * 5 * 6 + 30;
}
else
{
firstId = citizenManager.m_units.m_buffer[unitId].m_nextUnit;
citizenManager.ReleaseUnits(unitId);
vehicleData.m_citizenUnits = firstId;
n = (Mod.unit_number - 6) * 5 * 8 + 30;
}
citizenManager.CreateUnits(out firstId, ref random, 0, vehicleData.GetFirstVehicle(vehicleID), 0, 0, 0, n, 0);
vehicleData.m_citizenUnits = firstId;
}
return base.ArriveAtDestination(vehicleID, ref vehicleData);
}
}
}
玩家点评 (0人参与,0条评论)
热门评论
全部评论