偷轮子炮塔
This commit is contained in:
Binary file not shown.
83
1.6/1.6/Defs/HediffDefs/Hediffs_BodyParts_Turret.xml
Normal file
83
1.6/1.6/Defs/HediffDefs/Hediffs_BodyParts_Turret.xml
Normal file
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Defs>
|
||||
|
||||
<!--
|
||||
这是作为炮塔的武器定义 (ThingDef)
|
||||
它本身是一个不可装备、不可见的物品,仅作为 HediffComp 的数据源。
|
||||
HediffComp_TopTurret 会从这里读取武器的属性 (verb)、射程、冷却时间等,
|
||||
以及炮塔的图形 (graphicData)。
|
||||
-->
|
||||
|
||||
<ThingDef ParentName="BaseWeaponTurret">
|
||||
<defName>Gun_WULA_MiniTurretGun_ForHediff</defName>
|
||||
<label>tactical turret gun</label>
|
||||
<description>A simple automatic gun made to be mounted on a turret.</description>
|
||||
<graphicData>
|
||||
<texPath>Things/Building/TacticalTurret/TacticalTurret_Top</texPath>
|
||||
<graphicClass>Graphic_Single</graphicClass>
|
||||
</graphicData>
|
||||
<statBases>
|
||||
<AccuracyTouch>0.77</AccuracyTouch>
|
||||
<AccuracyShort>0.70</AccuracyShort>
|
||||
<AccuracyMedium>0.45</AccuracyMedium>
|
||||
<AccuracyLong>0.24</AccuracyLong>
|
||||
<RangedWeapon_Cooldown>4.8</RangedWeapon_Cooldown>
|
||||
<DeteriorationRate>0</DeteriorationRate>
|
||||
<Mass>5</Mass>
|
||||
<Flammability>0</Flammability>
|
||||
</statBases>
|
||||
<verbs>
|
||||
<li>
|
||||
<verbClass>Verb_Shoot</verbClass>
|
||||
<defaultProjectile>Bullet_TacticalTurret</defaultProjectile>
|
||||
<warmupTime>0</warmupTime>
|
||||
<range>19.9</range> <!-- Must be kept in sync with "explosion radius" of Grenade_TurretPack -->
|
||||
<ticksBetweenBurstShots>8</ticksBetweenBurstShots>
|
||||
<burstShotCount>2</burstShotCount>
|
||||
<soundCast>GunShotA</soundCast>
|
||||
<soundCastTail>GunTail_Light</soundCastTail>
|
||||
<muzzleFlashScale>9</muzzleFlashScale>
|
||||
<consumeFuelPerShot>1</consumeFuelPerShot>
|
||||
</li>
|
||||
</verbs>
|
||||
</ThingDef>
|
||||
|
||||
<!--
|
||||
这是 Hediff 定义本身
|
||||
你可以通过任何方式将这个 Hediff 添加给一个 Pawn,
|
||||
例如通过植入物、基因、甚至是开发人员命令。
|
||||
-->
|
||||
<HediffDef ParentName="ImplantHediffBase">
|
||||
<defName>WULA_ShoulderCannon</defName>
|
||||
<label>shoulder cannon</label>
|
||||
<description>A shoulder-mounted automated cannon that tracks and fires upon hostiles.</description>
|
||||
<spawnThingOnRemoved>Steel</spawnThingOnRemoved>
|
||||
<hediffClass>Hediff_Implant</hediffClass>
|
||||
<defaultLabelColor>(0.6, 0.6, 0.6)</defaultLabelColor>
|
||||
<isBad>false</isBad>
|
||||
|
||||
<!-- 这里是关键部分 -->
|
||||
<comps>
|
||||
<li Class="WulaFallenEmpire.HediffCompProperties_TopTurret">
|
||||
<!--
|
||||
指定上面定义的那个武器 ThingDef。
|
||||
这个组件会根据这个 ThingDef 创建一个虚拟的枪械并进行射击。
|
||||
-->
|
||||
<turretDef>Gun_WULA_MiniTurretGun_ForHediff</turretDef>
|
||||
|
||||
<!-- (可选) 炮塔旋转的偏移角度,0度通常指向右方 -->
|
||||
<angleOffset>0</angleOffset>
|
||||
|
||||
<!-- (可选) 是否自动攻击,默认为 true -->
|
||||
<autoAttack>true</autoAttack>
|
||||
</li>
|
||||
</comps>
|
||||
|
||||
<stages>
|
||||
<li>
|
||||
<!-- 你可以在这里添加其他效果,比如移动速度加成/减成等 -->
|
||||
</li>
|
||||
</stages>
|
||||
</HediffDef>
|
||||
|
||||
</Defs>
|
||||
268
Source/WulaFallenEmpire/HediffComp_TopTurret.cs
Normal file
268
Source/WulaFallenEmpire/HediffComp_TopTurret.cs
Normal file
@@ -0,0 +1,268 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
using RimWorld;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class HediffCompProperties_TopTurret : HediffCompProperties
|
||||
{
|
||||
public HediffCompProperties_TopTurret()
|
||||
{
|
||||
this.compClass = typeof(HediffComp_TopTurret);
|
||||
}
|
||||
|
||||
public ThingDef turretDef;
|
||||
|
||||
public float angleOffset;
|
||||
|
||||
public bool autoAttack = true;
|
||||
}
|
||||
|
||||
[StaticConstructorOnStartup]
|
||||
public class HediffComp_TopTurret : HediffComp, IAttackTargetSearcher
|
||||
{
|
||||
public Thing Thing
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Pawn;
|
||||
}
|
||||
}
|
||||
|
||||
private HediffCompProperties_TopTurret Props
|
||||
{
|
||||
get
|
||||
{
|
||||
return (HediffCompProperties_TopTurret)this.props;
|
||||
}
|
||||
}
|
||||
|
||||
public Verb CurrentEffectiveVerb
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.AttackVerb;
|
||||
}
|
||||
}
|
||||
|
||||
public LocalTargetInfo LastAttackedTarget
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.lastAttackedTarget;
|
||||
}
|
||||
}
|
||||
|
||||
public int LastAttackTargetTick
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.lastAttackTargetTick;
|
||||
}
|
||||
}
|
||||
|
||||
public CompEquippable GunCompEq
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.gun.TryGetComp<CompEquippable>();
|
||||
}
|
||||
}
|
||||
|
||||
public Verb AttackVerb
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GunCompEq.PrimaryVerb;
|
||||
}
|
||||
}
|
||||
|
||||
private bool WarmingUp
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.burstWarmupTicksLeft > 0;
|
||||
}
|
||||
}
|
||||
|
||||
private bool CanShoot
|
||||
{
|
||||
get
|
||||
{
|
||||
Pawn pawn;
|
||||
if ((pawn = (this.Pawn)) != null)
|
||||
{
|
||||
if (!pawn.Spawned || pawn.Downed || pawn.Dead || !pawn.Awake())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (pawn.stances.stunner.Stunned)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.TurretDestroyed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (pawn.IsColonyMechPlayerControlled && !this.fireAtWill)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
CompCanBeDormant compCanBeDormant = this.Pawn.TryGetComp<CompCanBeDormant>();
|
||||
return compCanBeDormant == null || compCanBeDormant.Awake;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TurretDestroyed
|
||||
{
|
||||
get
|
||||
{
|
||||
Pawn pawn;
|
||||
return (pawn = (this.Pawn)) != null && this.AttackVerb.verbProps.linkedBodyPartsGroup != null && this.AttackVerb.verbProps.ensureLinkedBodyPartsGroupAlwaysUsable && PawnCapacityUtility.CalculateNaturalPartsAverageEfficiency(pawn.health.hediffSet, this.AttackVerb.verbProps.linkedBodyPartsGroup) <= 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private Material TurretMat
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.turretMat == null)
|
||||
{
|
||||
this.turretMat = MaterialPool.MatFrom(this.Props.turretDef.graphicData.texPath);
|
||||
}
|
||||
return this.turretMat;
|
||||
}
|
||||
}
|
||||
|
||||
public bool AutoAttack
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.Props.autoAttack;
|
||||
}
|
||||
}
|
||||
|
||||
public override void CompPostMake()
|
||||
{
|
||||
base.CompPostMake();
|
||||
this.MakeGun();
|
||||
}
|
||||
|
||||
private void MakeGun()
|
||||
{
|
||||
this.gun = ThingMaker.MakeThing(this.Props.turretDef, null);
|
||||
this.UpdateGunVerbs();
|
||||
}
|
||||
|
||||
private void UpdateGunVerbs()
|
||||
{
|
||||
List<Verb> allVerbs = this.gun.TryGetComp<CompEquippable>().AllVerbs;
|
||||
for (int i = 0; i < allVerbs.Count; i++)
|
||||
{
|
||||
Verb verb = allVerbs[i];
|
||||
verb.caster = this.Pawn;
|
||||
verb.castCompleteCallback = delegate ()
|
||||
{
|
||||
this.burstCooldownTicksLeft = this.AttackVerb.verbProps.defaultCooldownTime.SecondsToTicks();
|
||||
};
|
||||
}
|
||||
}
|
||||
public override void CompPostTick(ref float severityAdjustment)
|
||||
{
|
||||
base.CompPostTick(ref severityAdjustment);
|
||||
if (!this.CanShoot)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (this.currentTarget.IsValid)
|
||||
{
|
||||
this.curRotation = (this.currentTarget.Cell.ToVector3Shifted() - this.Pawn.DrawPos).AngleFlat() + this.Props.angleOffset;
|
||||
}
|
||||
this.AttackVerb.VerbTick();
|
||||
if (this.AttackVerb.state != VerbState.Bursting)
|
||||
{
|
||||
if (this.WarmingUp)
|
||||
{
|
||||
this.burstWarmupTicksLeft--;
|
||||
if (this.burstWarmupTicksLeft == 0)
|
||||
{
|
||||
this.AttackVerb.TryStartCastOn(this.currentTarget, false, true, false, true);
|
||||
this.lastAttackTargetTick = Find.TickManager.TicksGame;
|
||||
this.lastAttackedTarget = this.currentTarget;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.burstCooldownTicksLeft > 0)
|
||||
{
|
||||
this.burstCooldownTicksLeft--;
|
||||
}
|
||||
if (this.burstCooldownTicksLeft <= 0 && this.Pawn.IsHashIntervalTick(10))
|
||||
{
|
||||
this.currentTarget = (Thing)AttackTargetFinder.BestShootTargetFromCurrentPosition(this, TargetScanFlags.NeedThreat | TargetScanFlags.NeedAutoTargetable, null, 0f, 9999f);
|
||||
if (this.currentTarget.IsValid)
|
||||
{
|
||||
this.burstWarmupTicksLeft = 1;
|
||||
return;
|
||||
}
|
||||
this.ResetCurrentTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetCurrentTarget()
|
||||
{
|
||||
this.currentTarget = LocalTargetInfo.Invalid;
|
||||
this.burstWarmupTicksLeft = 0;
|
||||
}
|
||||
|
||||
public override void CompExposeData()
|
||||
{
|
||||
base.CompExposeData();
|
||||
Scribe_Values.Look<int>(ref this.burstCooldownTicksLeft, "burstCooldownTicksLeft", 0, false);
|
||||
Scribe_Values.Look<int>(ref this.burstWarmupTicksLeft, "burstWarmupTicksLeft", 0, false);
|
||||
Scribe_TargetInfo.Look(ref this.currentTarget, "currentTarget");
|
||||
Scribe_Deep.Look<Thing>(ref this.gun, "gun", Array.Empty<object>());
|
||||
Scribe_Values.Look<bool>(ref this.fireAtWill, "fireAtWill", true, false);
|
||||
if (Scribe.mode == LoadSaveMode.PostLoadInit)
|
||||
{
|
||||
if (this.gun == null)
|
||||
{
|
||||
Log.Error("CompTurrentGun had null gun after loading. Recreating.");
|
||||
this.MakeGun();
|
||||
return;
|
||||
}
|
||||
this.UpdateGunVerbs();
|
||||
}
|
||||
}
|
||||
|
||||
private const int StartShootIntervalTicks = 10;
|
||||
|
||||
private static readonly CachedTexture ToggleTurretIcon = new CachedTexture("UI/Gizmos/ToggleTurret");
|
||||
|
||||
public Thing gun;
|
||||
|
||||
protected int burstCooldownTicksLeft;
|
||||
|
||||
protected int burstWarmupTicksLeft;
|
||||
|
||||
protected LocalTargetInfo currentTarget = LocalTargetInfo.Invalid;
|
||||
|
||||
private bool fireAtWill = true;
|
||||
|
||||
private LocalTargetInfo lastAttackedTarget = LocalTargetInfo.Invalid;
|
||||
|
||||
private int lastAttackTargetTick;
|
||||
|
||||
private float curRotation;
|
||||
|
||||
[Unsaved(false)]
|
||||
public Material turretMat;
|
||||
}
|
||||
}
|
||||
@@ -192,6 +192,7 @@
|
||||
<Compile Include="Patch_ForceTargetable.cs" />
|
||||
<Compile Include="Verb\VerbProperties_Excalibur.cs" />
|
||||
<Compile Include="Verb\Verb_Excalibur.cs" />
|
||||
<Compile Include="HediffComp_TopTurret.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Thing_ExcaliburBeam.cs" />
|
||||
|
||||
Reference in New Issue
Block a user