Guest User

Untitled

a guest
Jul 20th, 2014
306
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.72 KB | None | 0 0
  1. =================OpenRA, UberWaffe's Custom Warhead "How To Guide"=================
  2.  
  3. Let's say you want to make a new Warhead that does MindControl.
  4. You've already made two traits called MindController and MindControlable.
  5.  
  6. MindController - This goes on the actor doing the mind controlling, and needs to keep track of which actors is under its command.
  7.  
  8. MindControlable - This goes on the victim actors, and keeps track of whom (if any) is mind controlling it. And who it originally belonged to.
  9.  
  10. What you need is to create the link between these two when mind control occurs. I.e. tell the controller that the new controlable is now affected.
  11. And tell the victim whom its new boss is.
  12.  
  13.  
  14. So you make the new custom warhead. One which will setup these links.
  15. And since it is a warhead, you get the functionality of weapons for free (i.e. autotarget, range checks, target types, diplomacy checks, etc.)
  16.  
  17.  
  18. --Create a new Warhead class--
  19. So first, you make a class called MindControllerWarheadInfo.
  20.  
  21. public class MindControllerWarheadInfo
  22. {
  23.  
  24. }
  25.  
  26. The "WarheadInfo" part is standard. The "MindController" part is what you want it to be called.
  27.  
  28. In yaml you can create your warhead type by doing this:
  29.  
  30. Warhead@Whateveryouwant: MindController
  31.  
  32. The "Whateveryouwant" bit is anything you want, and is just for allowing multiple warheads on a single weapon.
  33. The ": MindController" part is so that the code will know what type of warhead you want.
  34. What the code does is take the bit after the ":" (in this case "MindController") and sticks "WarheadInfo" at the back, and then creates an instance of that class.
  35.  
  36.  
  37. --Give the new class some basic guts--
  38. Now, your new warhead class has to implement the "IWarheadInfo" interface, so that there is a standard way for the weapon code to interact with your new warhead.
  39. You will have to make functions for all the bits of the interface.
  40.  
  41. But since the valid checks are done in a rather standard fashion (i.e. we check allowed types against the victim's TargetTypes), there is also a base warhead class called BaseWarhead.
  42. If you inherit from BaseWarhead, like this:
  43.  
  44. public class MindControllerWarheadInfo : BaseWarhead, IWarheadInfo
  45. {
  46.  
  47. public MindControllerWarheadInfo() : base() { }
  48. }
  49.  
  50. Then your warhead can already understand:
  51. * What is valid targets and what is not (including diplomacy keywords such as "Ally", "Neutral", Enemy").
  52. * How to load its values from yaml.
  53.  
  54. But it will not know how to:
  55. * Do an impact. In fact, its DoImpact() simply logs a warning to the debug.log
  56. * Check for effectiveness. It will always say it is 100% effective against everything. (Arrogant little warhead.)
  57.  
  58.  
  59. --Tell your warhead what it must do on an impact--
  60. Allright, so now we want to make our MindControl warhead create the link.
  61. So we have to put something inside its DoImpact.
  62.  
  63. public new void DoImpact(WPos pos, WeaponInfo weapon, Actor firedBy, float firepowerModifier)
  64. {
  65.  
  66. }
  67.  
  68. But what to put in there?
  69.  
  70. Let us take a look at the DoImpact of DamagerWarhead in GameRules > Warheads.
  71.  
  72. We can see it does a check for what type of damage model it is. We don't have that, so we look inside the Normal damage model just because.
  73. Ah!
  74. var hitActors = world.FindActorsInCircle(pos, maxSpread);
  75.  
  76. It finds all the actors within the spread of the warhead.
  77. We probably also have spread, so we'll have to do the same.
  78. (Remember, that warheads detonate at a position, even when targeting an actor. So we need some sort of spread check
  79. if we want to affect actors and not just positions.)
  80.  
  81. Now, we look further:
  82. foreach (var victim in hitActors)
  83.  
  84. Ah, it iterates over all the victims it found within range of its spread. Then for each victim, it figures out what happened.
  85. Firstly, it makes sure that the victim can be affected by the warhead:
  86. if (IsValidAgainst(victim, firedBy))
  87.  
  88. Then it figures out how much damage to do and (here comes another important bit) does this:
  89. victim.InflictDamage(firedBy, damage, this);
  90.  
  91. Effectively it calls the InflictDamage() function from the Health trait on the actor!
  92.  
  93. Aha! So we can do something similar for our MindControlable and MindController traits!
  94.  
  95. public new void DoImpact(WPos pos, WeaponInfo weapon, Actor firedBy, float firepowerModifier)
  96. {
  97. var world = firedBy.World;
  98. var targetTile = world.Map.CellContaining(pos);
  99.  
  100. var hitActors = world.FindActorsInCircle(pos, Spread.Range);
  101.  
  102. foreach (var victim in hitActors)
  103. {
  104. if (IsValidAgainst(victim, firedBy))
  105. {
  106.  
  107. }
  108. }
  109. }
  110.  
  111. But wait!! Health is always included, but our traits might not be, so we will have to do some sort of check to make sure the victim has the MindControlable trait.
  112. So we will need to overwrite IsValidAgainst from our inherited base, using the "new" flag.
  113.  
  114. public new bool IsValidAgainst(Actor victim, Actor firedBy)
  115. {
  116. //A target type is valid if it is in the valid targets list, and not in the invalid targets list.
  117. return CheckTargetList(victim, firedBy, this.ValidTargets) &&
  118. !CheckTargetList(victim, firedBy, this.InvalidTargets);
  119. }
  120.  
  121. So, since we can only mindcontrol victims that have the MindControlable trait, we add that into the IsValidAgainst check.
  122.  
  123. public new bool IsValidAgainst(Actor victim, Actor firedBy)
  124. {
  125. var brainTrait = victim.TraitOrDefault<MindControlable>();
  126. if (brainTrait == null)
  127. return false;
  128.  
  129. //A target type is valid if it is in the valid targets list, and not in the invalid targets list.
  130. return CheckTargetList(victim, firedBy, this.ValidTargets) &&
  131. !CheckTargetList(victim, firedBy, this.InvalidTargets);
  132. }
  133.  
  134. This now means that if we check a victim that doesn't have the trait, our IsValidAgainst will tell us "No! No touchies!" and we will know we can't mindcontrol it.
  135. Now back to DoImpact:
  136.  
  137. public new void DoImpact(WPos pos, WeaponInfo weapon, Actor firedBy, float firepowerModifier)
  138. {
  139. var world = firedBy.World;
  140. var targetTile = world.Map.CellContaining(pos);
  141.  
  142. var hitActors = world.FindActorsInCircle(pos, Spread.Range);
  143.  
  144. foreach (var victim in hitActors)
  145. {
  146. if (IsValidAgainst(victim, firedBy))
  147. {
  148. var brainTrait = victim.TraitOrDefault<MindControlable>();
  149. brainTrait.MyMindIsYours(firedBy); //We call the MyMindIsYours(Actor thePuppeteer) function on the MindControlable function to create the first half of the link.
  150.  
  151. var puppeteerTrait = firedBy.TraitOrDefault<MindController>();
  152. puppeteerTrait.HisMindIsWeak(victim); //We call the HisMindIsWeak(Actor thePuppet) function on the MindController function to create the other half of the link.
  153. }
  154. }
  155. }
  156.  
  157. And we are nearly done! We need some other checks, but for the most part our new warhead can now setup mindcontrol links!
  158.  
  159. We probably still want to update IsValidAgainst to also check that the mindcontroller has spare capacity:
  160.  
  161. public new bool IsValidAgainst(Actor victim, Actor firedBy)
  162. {
  163. var brainTrait = victim.TraitOrDefault<MindControlable>();
  164. if (brainTrait == null)
  165. return false;
  166.  
  167. var superiorBrainTrait = firedBy.TraitOrDefault<MindController>();
  168. if (superiorBrainTrait == null)
  169. return false; //Mind Controller must be able to mind control, otherwise this won't work.
  170.  
  171. if (superiorBrainTrait.HasSpareCapacity() == false)
  172. return false; //Sorry, the mind can take no more strain!
  173.  
  174. //A target type is valid if it is in the valid targets list, and not in the invalid targets list.
  175. return CheckTargetList(victim, firedBy, this.ValidTargets) &&
  176. !CheckTargetList(victim, firedBy, this.InvalidTargets);
  177. }
  178.  
  179. --Make the YAML happen--
  180. Warhead@theleftbrain: MindController
  181. Spread: 42
Advertisement
Add Comment
Please, Sign In to add comment