Advertisement
comfix

Rimworld Modding Issue

Apr 19th, 2015
331
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.27 KB | None | 0 0
  1. //This is the fine tuned source code of the wind turbine
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6.  
  7. using UnityEngine;
  8. using Verse;
  9. using RimWorld;
  10.  
  11.  
  12. namespace WindTurbine
  13. {
  14. /// <summary>
  15. /// This is a wind tubine building
  16. /// </summary>
  17. class Building_PowerPlantWindTurbine : Building_PowerPlant
  18. {
  19.  
  20. #region Variables
  21. // ==================================
  22.  
  23.  
  24. public static Graphic[] graphic = null;
  25.  
  26. private const int arraySize = 12; // Turn animation off => set to 1
  27. private string graphicPathAdditionWoNumber = "_frame"; // everything before this will be used for the other file names
  28.  
  29. private int activeGraphicFrame = 0;
  30. private int activeGraphicFrameOld = -1;
  31. private int ticksSinceUpdateGraphic;
  32. private const int updateAnimationEveryXTicks = 10;
  33.  
  34.  
  35. public int updateWeatherEveryXTicks = 250;
  36. private int ticksSinceWeatherUpdate;
  37.  
  38. private List<IntVec3> windPathCells;
  39. private bool windPathBlocked;
  40. private List<Thing> windPathBlockedByThings;
  41. private List<IntVec3> windPathBlockedCells;
  42. private const float powerReductionPercentPerObstacle = 0.2f;
  43.  
  44. private float maxWindIntensity = 0f;
  45.  
  46. private const string translateWindPathIsBlocked = "WindTurbineExample_WindPathIsBlocked";
  47. private const string translateWindPathIsBlockedBy = "WindTurbineExample_WindPathIsBlockedBy";
  48. private const string translateWindPathIsBlockedByRoof = "WindTurbineExample_WindPathIsBlockedByRoof";
  49.  
  50. private static Vector2 BarSize;
  51. private readonly static Material BarFilledMat = SolidColorMaterials.SimpleSolidColorMaterial(new Color(0.5f, 0.475f, 0.1f));
  52. private readonly static Material BarUnfilledMat = SolidColorMaterials.SimpleSolidColorMaterial(new Color(0.15f, 0.15f, 0.15f));
  53.  
  54. #endregion
  55.  
  56.  
  57. #region Setup Work
  58. // ==================================
  59.  
  60. /// <summary>
  61. /// Do something after the object is spawned into the world
  62. /// </summary>
  63. public override void SpawnSetup()
  64. {
  65. base.SpawnSetup();
  66.  
  67. BarSize = new Vector2(def.size.z - 0.95f, 0.14f);
  68.  
  69. maxWindIntensity = 0f;
  70. foreach (WeatherDef wDef in DefDatabase<WeatherDef>.AllDefs)
  71. {
  72. if (wDef.windSpeedFactor > maxWindIntensity)
  73. maxWindIntensity = wDef.windSpeedFactor;
  74. }
  75.  
  76. CheckWindPathBlocked(ref windPathCells, out windPathBlockedCells, out windPathBlockedByThings);
  77. }
  78.  
  79.  
  80. /// <summary>
  81. /// To save and load actual values (savegame-data)
  82. /// </summary>
  83. public override void ExposeData()
  84. {
  85. base.ExposeData();
  86. Scribe_Values.LookValue<int>(ref ticksSinceWeatherUpdate, "updateCounter");
  87. }
  88.  
  89.  
  90. /// <summary>
  91. /// Import the graphics
  92. /// </summary>
  93. private void UpdateGraphics()
  94. {
  95. // resize the graphic array
  96. graphic = new Graphic_Single[arraySize];
  97.  
  98. // Get the base path (without _frameXX)
  99. int indexOf_frame = def.graphicPath.ToLower().LastIndexOf(graphicPathAdditionWoNumber);
  100. string graphicRealPathBase = def.graphicPath.Remove(indexOf_frame);
  101.  
  102. // fill the graphic array
  103. for (int i = 0; i < arraySize; i++)
  104. {
  105. string graphicRealPath = graphicRealPathBase + graphicPathAdditionWoNumber + (i + 1).ToString();
  106.  
  107. // Set the graphic
  108. graphic[i] = GraphicDatabase.Get<Graphic_Single>(graphicRealPath, def.shader, def.DrawSize, def.defaultColor, def.defaultColorTwo);
  109. }
  110. }
  111.  
  112.  
  113. #endregion
  114.  
  115.  
  116. #region Ticker
  117. // ==================================
  118.  
  119. /// <summary>
  120. /// This is used, when the Ticker is set to Normal
  121. /// This Tick is done often (60 times per second)
  122. /// </summary>
  123. public override void Tick()
  124. {
  125. base.Tick();
  126.  
  127.  
  128. // Power off
  129. if ( powerComp == null || !powerComp.PowerOn )
  130. {
  131. activeGraphicFrame = 0;
  132. powerComp.powerOutputInt = -0.0f;
  133. return;
  134. }
  135.  
  136.  
  137. if (powerComp.powerOutputInt != 0)
  138. {
  139. ticksSinceUpdateGraphic++;
  140. if (ticksSinceUpdateGraphic >= updateAnimationEveryXTicks)
  141. {
  142. ticksSinceUpdateGraphic = 0;
  143. activeGraphicFrame++;
  144. if (activeGraphicFrame >= arraySize)
  145. activeGraphicFrame = 0;
  146.  
  147. UpdateGraphicForAnimation();
  148. }
  149. }
  150.  
  151.  
  152.  
  153. // Power update based on weather
  154. // This is used instead of TickRare to prevent the possibility, that all turbines check the wind path at the same time after loading
  155. ticksSinceWeatherUpdate++;
  156. if (ticksSinceWeatherUpdate >= updateWeatherEveryXTicks)
  157. {
  158. ticksSinceWeatherUpdate = 0;
  159. WeatherDef weather = Find.WeatherManager.curWeather;
  160. powerComp.powerOutputInt = -(powerComp.props.basePowerConsumption * weather.windSpeedFactor);
  161.  
  162. // Just for a little bit wind randomness..
  163. powerComp.powerOutputInt += (float)Rand.RangeInclusive(-20, 20);
  164.  
  165. // If obstacled, reduce production
  166. windPathBlocked = CheckWindPathBlocked(ref windPathCells, out windPathBlockedCells, out windPathBlockedByThings);
  167.  
  168. if (windPathBlocked)
  169. {
  170. float reduction = 0;
  171. for (int i = 0; i < windPathBlockedCells.Count; i++)
  172. reduction += powerComp.powerOutputInt * powerReductionPercentPerObstacle;
  173.  
  174. if (reduction < powerComp.powerOutputInt)
  175. powerComp.powerOutputInt -= reduction;
  176. else
  177. {
  178. powerComp.powerOutputInt = -0.0f;
  179. activeGraphicFrame = 0;
  180. UpdateGraphicForAnimation();
  181. }
  182. }
  183. }
  184. }
  185.  
  186.  
  187.  
  188. #endregion
  189.  
  190.  
  191. #region Graphics / Inspections
  192. // ==================================
  193.  
  194. /// <summary>
  195. /// This returns the graphic of the object.
  196. /// The renderer will draw the needed object graphic from here.
  197. /// </summary>
  198. public override Graphic Graphic
  199. {
  200. get
  201. {
  202.  
  203. if (graphic == null || graphic[0] == null)
  204. {
  205. UpdateGraphics();
  206. // Graphic couldn't be loaded? (Happends after load for a while)
  207. if (graphic == null || graphic[0] == null)
  208. return base.Graphic;
  209. }
  210.  
  211. if (graphic[activeGraphicFrame] != null)
  212. return graphic[activeGraphicFrame];
  213.  
  214. return base.Graphic;
  215. }
  216. }
  217.  
  218.  
  219.  
  220. /// <summary>
  221. /// Draw power display
  222. /// </summary>
  223. public override void Draw()
  224. {
  225. base.Draw();
  226. GenDraw.FillableBarRequest fillableBarRequest = new GenDraw.FillableBarRequest()
  227. {
  228. center = DrawPos + (Vector3.up * 0.1f),
  229. size = BarSize,
  230. fillPercent = powerComp.powerOutputInt / (-powerComp.props.basePowerConsumption * maxWindIntensity),
  231. filledMat = BarFilledMat,
  232. unfilledMat = BarUnfilledMat,
  233. margin = 0.15f
  234. };
  235.  
  236. IntRot rotation = base.Rotation;
  237. rotation.Rotate(RotationDirection.Clockwise);
  238. fillableBarRequest.rotation = rotation;
  239. GenDraw.DrawFillableBar(fillableBarRequest);
  240. }
  241.  
  242.  
  243. /// <summary>
  244. /// This string will be shown when the object is selected (focus)
  245. /// </summary>
  246. public override string GetInspectString()
  247. {
  248. StringBuilder stringBuilder = new StringBuilder();
  249.  
  250. stringBuilder.Append(base.GetInspectString());
  251.  
  252. stringBuilder.AppendLine();
  253.  
  254. if (windPathBlocked)
  255. {
  256. stringBuilder.Append(translateWindPathIsBlocked.Translate());
  257. stringBuilder.AppendLine();
  258.  
  259. Thing blocker = null;
  260. if (windPathBlockedByThings != null)
  261. blocker = windPathBlockedByThings[0];
  262.  
  263. if (blocker != null)
  264. stringBuilder.Append(translateWindPathIsBlockedBy.Translate() + " " + blocker.Label);
  265. else
  266. stringBuilder.Append(translateWindPathIsBlockedByRoof.Translate());
  267.  
  268. }
  269.  
  270. // return the complete string
  271. return stringBuilder.ToString();
  272. }
  273.  
  274.  
  275. /// <summary>
  276. /// Draw the wind path
  277. /// </summary>
  278. public override void DrawExtraSelectionOverlays()
  279. {
  280. base.DrawExtraSelectionOverlays();
  281.  
  282. if (windPathCells != null)
  283. GenDraw.DrawFieldEdges(windPathCells);
  284. }
  285.  
  286. #endregion
  287.  
  288.  
  289. #region Functions
  290.  
  291. private void UpdateGraphicForAnimation()
  292. {
  293. if (activeGraphicFrame == activeGraphicFrameOld)
  294. return;
  295.  
  296. activeGraphicFrameOld = activeGraphicFrame;
  297.  
  298. // Tell the MapDrawer that here is something thats changed
  299. Find.MapDrawer.MapChanged(Position, MapChangeType.Things, true, false);
  300. }
  301.  
  302.  
  303. // Check if an object is blocking the wind flow
  304. // Check for Thing.def.altitudeLayer == BuildingTall
  305. // blockedThings are correlating to blockedCells, but can have null fields. This means that corresponding cell is roofed.
  306. private bool CheckWindPathBlocked(ref List<IntVec3> checkCells, out List<IntVec3> blockedCells, out List<Thing> blockedByThings)
  307. {
  308. if (checkCells == null)
  309. checkCells = new List<IntVec3>();
  310.  
  311. if (checkCells.Count() == 0)
  312. {
  313. IEnumerable<IntVec3> tmpCells = GetCellsOfConeBeforeAndBehindObject(Position, Rotation, def.size);
  314. checkCells.AddRange(tmpCells);
  315. }
  316.  
  317. blockedCells = new List<IntVec3>();
  318. blockedByThings = new List<Thing>();
  319.  
  320. for (int i = 0; i < checkCells.Count; i++)
  321. {
  322. IntVec3 cell = checkCells[i];
  323.  
  324. // roofed?
  325. if (Find.RoofGrid.Roofed(cell))
  326. {
  327. blockedByThings.Add(null);
  328. blockedCells.Add(cell);
  329. continue;
  330. }
  331.  
  332. // blocked?
  333. List<Thing> workThings = Find.ThingGrid.ThingsListAt(cell);
  334. for (int j = 0; j < workThings.Count; j++ )
  335. {
  336. Thing workThing = workThings[j];
  337. if (workThing.def.altitudeLayer == AltitudeLayer.BuildingTall)
  338. {
  339. blockedByThings.Add(workThing);
  340. blockedCells.Add(cell);
  341. break;
  342. }
  343. }
  344. }
  345.  
  346. return blockedCells.Count > 0;
  347. }
  348.  
  349.  
  350. // Find the cells of the wind path before and behind the wind turbine
  351. private IEnumerable<IntVec3> GetCellsOfConeBeforeAndBehindObject(IntVec3 thingCenter, IntRot thingRot, IntVec2 thingSize)
  352. {
  353. // Base cone:
  354. // +++ +xx+
  355. // +++++ ++xx++
  356. // XXXXX ++xx++
  357. // XXXXX ++xx++
  358. // +++++ ++xx++
  359. // +++ +xx+
  360.  
  361. // Description:
  362. // X - Object
  363. // + - Returned cells
  364.  
  365. int numBaseX1, numBaseX2, numBaseZ1, numBaseZ2;
  366. int num1X1, num1X2, num2X1, num2X2, num1Z1, num1Z2, num2Z1, num2Z2;
  367. int num3X1, num3X2, num3Z1, num3Z2, num4X1, num4X2, num4Z1, num4Z2;
  368.  
  369. // change to resize wind path
  370. int extensionLengthFront = 5;
  371. int extensionLengthBack = 2;
  372.  
  373. // Find base points to work with
  374. // X1 and Z1 are the lower values
  375. if (thingRot == IntRot.north)
  376. {
  377. numBaseX1 = thingCenter.x - (thingSize.x + 1) / 2 + 1;
  378. numBaseX2 = numBaseX1 + thingSize.x - 1;
  379. numBaseZ1 = thingCenter.z - (thingSize.z + 1) / 2 + 1;
  380. numBaseZ2 = numBaseZ1 + thingSize.z - 1;
  381. }
  382. else if (thingRot == IntRot.east)
  383. {
  384. numBaseX1 = thingCenter.x - (thingSize.z + 1) / 2 + 1;
  385. numBaseX2 = numBaseX1 + thingSize.z - 1;
  386. numBaseZ1 = thingCenter.z - thingSize.x / 2;
  387. numBaseZ2 = numBaseZ1 + thingSize.x - 1;
  388. }
  389. else if (thingRot == IntRot.south)
  390. {
  391. numBaseX1 = thingCenter.x - thingSize.x / 2;
  392. numBaseX2 = numBaseX1 + thingSize.x - 1;
  393. numBaseZ1 = thingCenter.z - thingSize.z / 2;
  394. numBaseZ2 = numBaseZ1 + thingSize.z - 1;
  395. }
  396. else //if ( thingRot == IntRot.west )
  397. {
  398. numBaseX1 = thingCenter.x - thingSize.z / 2;
  399. numBaseX2 = numBaseX1 + thingSize.z - 1;
  400. numBaseZ1 = thingCenter.z - (thingSize.x + 1) / 2 + 1;
  401. numBaseZ2 = numBaseZ1 + thingSize.x - 1;
  402. }
  403.  
  404. IntVec3 intVec3;
  405.  
  406. // Get the cells from here if the rotation is north or south
  407. if (Rotation == IntRot.north || Rotation == IntRot.south)
  408. {
  409. // Base cone, inner part
  410. num1X1 = numBaseX1 + 0;
  411. num1X2 = numBaseX2 + 0;
  412. num1Z1 = numBaseZ1 - 1;
  413. num1Z2 = numBaseZ2 + 1;
  414. // Base cone, outer part
  415. num2X1 = numBaseX1 + 0; // original: +1
  416. num2X2 = numBaseX2 + 0; // original: -1
  417. num2Z1 = numBaseZ1 - 2;
  418. num2Z2 = numBaseZ2 + 2;
  419.  
  420. if (Rotation == IntRot.north)
  421. {
  422. // Extended dome
  423. num3X1 = numBaseX1 + 1;
  424. num3X2 = numBaseX2 - 1;
  425. num3Z1 = numBaseZ1 - 2 - extensionLengthBack;
  426. num3Z2 = numBaseZ1 - 2;
  427.  
  428. num4X1 = numBaseX1 + 1;
  429. num4X2 = numBaseX2 - 1;
  430. num4Z1 = numBaseZ2 + (extensionLengthFront - 2);
  431. num4Z2 = numBaseZ2 + (extensionLengthFront + 2);
  432. }
  433. else //if (Rotation == IntRot.south)
  434. {
  435. // Extended dome
  436. num3X1 = numBaseX1 + 1;
  437. num3X2 = numBaseX2 - 1;
  438. num3Z1 = numBaseZ1 - (extensionLengthFront + 2);
  439. num3Z2 = numBaseZ1 - (extensionLengthFront - 2);
  440.  
  441. num4X1 = numBaseX1 + 1;
  442. num4X2 = numBaseX2 - 1;
  443. num4Z1 = numBaseZ2 + 2;
  444. num4Z2 = numBaseZ2 + 2 + extensionLengthBack;
  445. }
  446.  
  447.  
  448. intVec3 = new IntVec3(num1X1, 0, num1Z1);
  449. do
  450. {
  451. yield return intVec3;
  452. intVec3.x += 1;
  453. } while (intVec3.x <= num1X2);
  454.  
  455. intVec3 = new IntVec3(num2X1, 0, num2Z1);
  456. do
  457. {
  458. yield return intVec3;
  459. intVec3.x += 1;
  460. } while (intVec3.x <= num2X2);
  461.  
  462.  
  463. intVec3 = new IntVec3(num1X1, 0, num1Z2);
  464. do
  465. {
  466. yield return intVec3;
  467. intVec3.x += 1;
  468. } while (intVec3.x <= num1X2);
  469.  
  470. intVec3 = new IntVec3(num2X1, 0, num2Z2);
  471. do
  472. {
  473. yield return intVec3;
  474. intVec3.x += 1;
  475. } while (intVec3.x <= num2X2);
  476.  
  477.  
  478. // Extended dome
  479. intVec3 = new IntVec3(num3X1 - 1, 0, num3Z1);
  480. while (intVec3.x < num3X2 || intVec3.z < num3Z2)
  481. {
  482. if (intVec3.x < num3X2)
  483. {
  484. intVec3.x += 1;
  485. }
  486. else if (intVec3.z <= num3Z2)
  487. {
  488. intVec3.x = num3X1;
  489. intVec3.z += 1;
  490. }
  491. yield return intVec3;
  492. }
  493.  
  494. intVec3 = new IntVec3(num4X1 - 1, 0, num4Z1);
  495. while (intVec3.x < num4X2 || intVec3.z < num4Z2)
  496. {
  497. if (intVec3.x < num4X2)
  498. {
  499. intVec3.x += 1;
  500. }
  501. else if (intVec3.z <= num4Z2)
  502. {
  503. intVec3.x = num4X1;
  504. intVec3.z += 1;
  505. }
  506. yield return intVec3;
  507. }
  508.  
  509. }
  510.  
  511. // Get the cells from here if the rotation is east or west
  512. if (Rotation == IntRot.east || Rotation == IntRot.west)
  513. {
  514. // Base cone, inner part
  515. num1X1 = numBaseX1 - 1;
  516. num1X2 = numBaseX2 + 1;
  517. num1Z1 = numBaseZ1 + 0;
  518. num1Z2 = numBaseZ2 + 0;
  519. // Base cone, outer part
  520. num2X1 = numBaseX1 - 2;
  521. num2X2 = numBaseX2 + 2;
  522. num2Z1 = numBaseZ1 + 0; // original: +1
  523. num2Z2 = numBaseZ2 + 0; // original: -1
  524.  
  525. if (Rotation == IntRot.east)
  526. {
  527. // Extended dome
  528. num3X1 = numBaseX1 - 2 - extensionLengthBack;
  529. num3X2 = numBaseX1 - 2;
  530. num3Z1 = numBaseZ1 + 1;
  531. num3Z2 = numBaseZ2 - 1;
  532.  
  533. num4X1 = numBaseX2 + (extensionLengthFront - 2);
  534. num4X2 = numBaseX2 + (extensionLengthFront + 2);
  535. num4Z1 = numBaseZ1 + 1;
  536. num4Z2 = numBaseZ2 - 1;
  537. }
  538. else //if (Rotation == IntRot.west)
  539. {
  540. // Extended dome
  541. num3X1 = numBaseX1 - (extensionLengthFront + 2);
  542. num3X2 = numBaseX1 - (extensionLengthFront - 2);
  543. num3Z1 = numBaseZ1 + 1;
  544. num3Z2 = numBaseZ2 - 1;
  545.  
  546. num4X1 = numBaseX2 + 2;
  547. num4X2 = numBaseX2 + 2 + extensionLengthBack;
  548. num4Z1 = numBaseZ1 + 1;
  549. num4Z2 = numBaseZ2 - 1;
  550. }
  551.  
  552.  
  553. intVec3 = new IntVec3(num1X1, 0, num1Z1);
  554. do
  555. {
  556. yield return intVec3;
  557. intVec3.z += 1;
  558. } while (intVec3.z <= num1Z2);
  559.  
  560. intVec3 = new IntVec3(num2X1, 0, num2Z1);
  561. do
  562. {
  563. yield return intVec3;
  564. intVec3.z += 1;
  565. } while (intVec3.z <= num2Z2);
  566.  
  567.  
  568. intVec3 = new IntVec3(num1X2, 0, num1Z1);
  569. do
  570. {
  571. yield return intVec3;
  572. intVec3.z += 1;
  573. } while (intVec3.z <= num1Z2);
  574.  
  575. intVec3 = new IntVec3(num2X2, 0, num2Z1);
  576. do
  577. {
  578. yield return intVec3;
  579. intVec3.z += 1;
  580. } while (intVec3.z <= num2Z2);
  581.  
  582.  
  583. // Extended dome
  584. intVec3 = new IntVec3(num3X1 - 1, 0, num3Z1);
  585. while (intVec3.x < num3X2 || intVec3.z < num3Z2)
  586. {
  587. if (intVec3.x < num3X2)
  588. {
  589. intVec3.x += 1;
  590. }
  591. else if (intVec3.z <= num3Z2)
  592. {
  593. intVec3.x = num3X1;
  594. intVec3.z += 1;
  595. }
  596. yield return intVec3;
  597. }
  598.  
  599. intVec3 = new IntVec3(num4X1 - 1, 0, num4Z1);
  600. while (intVec3.x < num4X2 || intVec3.z < num4Z2)
  601. {
  602. if (intVec3.x < num4X2)
  603. {
  604. intVec3.x += 1;
  605. }
  606. else if (intVec3.z <= num4Z2)
  607. {
  608. intVec3.x = num4X1;
  609. intVec3.z += 1;
  610. }
  611. yield return intVec3;
  612. }
  613. }
  614. }
  615.  
  616.  
  617. #endregion
  618.  
  619. }
  620. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement