Announcement

Collapse
No announcement yet.

Predator Missile from COD: Modern Warfare 2

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Predator Missile from COD: Modern Warfare 2

    Hi there. I'm trying to imitate the Predator Missile from Call of Duty: Modern Warfare 2. I’ve made a lot of progress so far, including spawning the Redeemer’s guided warhead at the top of the map and randomly setting its rotation within certain parameters, as well as replacing its ability to remote detonate in midair with the ability to boost. Other problems have me stumped though, and I was hoping I could receive a little help.

    First, how do I transfer controllers for a given pawn? Here's a bit of code unrelated to the Predator:

    Code:
    event PreBeginPlay()
    {
    	local Controller C, newC;
    	local Pawn P;
    
     	for (C = Level.ControllerList; C != None; C = C.NextController)
     	{
     		  if (C.Pawn != None)
     		  {
     			P = C.Pawn;
     			newC = spawn(class'TestController');
    			newC.possess(P);
     		  }
        }
    }
    This code is part of a mutator which, as you can see, goes through the ControllerList at the start of the match, attempting to swap controllers for all existing pawns. It simply does not work. Is this because pawns don't exist along with all other actors when the level finishes loading, but only after the match actually begins? If so, can someone tell me what function I would want to override to affect pawns but have the appearance of taking place at the start of the match?

    Also, I did try the same code in a Timer that is set by the mutator in PreBeginPlay(). It works, kind of. The code in my custom controller class is executed (in this case maxing out Adrenaline), but the weapon you are holding stops updating its rotation, only its location (i.e., it still follows you around, but it remains pointing in the direction it was when the Timer was executed). It also won't fire, and I imagine I’ve killed quite a bit of other functionality too. Now, I tried unpossessing the pawn first, but that doesn't work either. It ended up giving me a spectator’s view. Does anyone have any insights?

    This problem is relevant to the Predator because I need to pass off the guided warhead to my own controller. Speaking of which, does anyone know where the code is that limits the pitch (how far up or down you can rotate your view) of the Redeemer’s guided warhead? I think it’s somewhere in PlayerController, but I can’t seem to find it. There’s a block in PlayerCalcView that asks whether or not the pawn is a projectile, but it only seems to modify location, and not rotation. I’d like to allow the warhead to aim all the way down, but strictly limit how far up it can aim. The Predator isn’t supposed to be able to aim very high, certainly not all the way up.

    Next, I’m trying to find another section of code, but this time I don’t know if it even exists, and I’d like to know if it does before I search feverishly for it for nothing. It’s the current level’s dimensions, and I need them to determine how high exactly I need to be spawning my Predator. I loaded up CTF-1on1-Joust and tried firing the missile, but because the level isn’t as high as DM-Morpheus3, my usual test map, it insta-killed me. It was rather humorous, but I don’t want it happening when the missile is complete. So, does anyone know if I can obtain these measurements, and possibly where they might be?

    If you read all of that, I salute you, and thank you for any answers you might be able to offer. I’ll ask further questions I have as I progress through this mod.

    #2
    Do you want the predator missile to act like a weapon (eg: you flip out a laptop and then you can spawn a missile from a circling predator?). If so then I would think extending the redeemer is the way to go, and just tweak stuff from there (eg spawn a dummy predator that circles somewhere in the level and use its location). You can use the viewTarget variable to choose a different actor to have the player view from while still in possession of their own pawn.

    And you need to read through the GameInfo class to see the spawn order, but mutators should be spawned/added before controller for bots and players are spawned, so the controller list should be empty during prebeginplay/beginplay/postbeginplay/postnetbeginplay.

    Pitch limiting (the LimitPitch function actually) is located in the pawn class (of which the redeemerWarhead is an extension). It is called from within the UpdateRotation function in the playercontroller class.

    Level Dimensions: There are no script accessible variables that have this information. Since any given map could be a completely "indoor" map and (unlike COD maps I assume) there are no required mapper placed "center of the sky" actors, there isn't too much to work with. The best you can do is use the location of AI navigation points (using vector math & traces to determine where the best location is) which should always be in "player accessible" space (as opposed to the skybox), or search for an Ion Cannon (if present) and spawn a predator there. In my CODMW mutator (part of my YARM mod), I added aerial bombardments for killstreaks based on the code for the bomber run that occurs (ONSAutoBomber) when you use the laser tagger weapon (ONSPainter). Take a look at that source code for determining if there is enough "air" above your preferred location.

    I think Wormbo had a weapon mutator with guided rockets (Mercury Missiles?) or a viewing camera that may also help (I don't think it had you "possess" the rocket, it just switched camera views and used the players' rotation).

    Comment


      #3
      Awesome, I didn’t know whether to expect such a great answer today. Yes, I intend for the Predator to act like a weapon (as you said, flip out a laptop, then press either button to fire and guide the missile down – I’m no artist, though, just practicing coding, so unless I can recruit someone to create the laptop it probably will never get done). Whether or not to spawn an actual Predator and have the missile fire from that was on my “things to be determined” list. I’m currently firing it from the center of the map, but even in testing this has already gotten old. I was going to maybe randomize the spawn location based on the length and width of the map, but now it sounds like I won’t be able to do that. Ah well.

      I dug through the PlayerController class and found the SetViewTarget function. I needed this because ViewTarget is a constant. I used it in the following code to switch from the player’s initial perspective to that of a bot’s.

      Code:
      function Timer()
      {
                   local Controller C, X;
      
                   for (C = Level.ControllerList; C != None; C = C.NextController)
                   {
                                if (C.IsA('AIController'))
                                {
                                             X = C;
                                }
                   }
      
                   for (C = Level.ControllerList; C != None; C = C.NextController)
                   {
                                if (C.IsA('PlayerController'))
                                {
                                             PlayerController(C).SetViewTarget(X);
                                }
                   }
      }
      This was contained in a mutator that set the timer in PreBeginPlay(). Seeing the world through a bot’s eyes is pretty cool (the fact that their view banks was new to me), but it doesn’t really help me with the Predator. I had no control over the bot but was still able to shoot from my original character (I had no other bots on the level and I could hear myself offscreen). I assume I could move and jump with my original character too. I think what I need is in fact to take possession of the guided warhead. RedeemerGuidedFire does this, but I need to be able to do it with my own controller class. Here’s my attempt at this:

      Code:
      function Projectile SpawnProjectile(Vector Start, Rotator Dir)
      {
                   local RedeemerWarhead Warhead;
                   local PlayerController Possessor;
                   local class<PredatorController> TestController;
                   local rotator myRot;
      
                   myRot = decideRotation();
      
                   Warhead = Weapon.Spawn(class'PredatorMissile', Instigator,, myVect, myRot);
      
                   if (Warhead != None)
                   {
                                Warhead.OldPawn = Instigator;
                                Warhead.PlaySound(FireSound);
                                Possessor = PlayerController(Instigator.Controller);
                                Possessor.bAltFire = 0;
                                if ( Possessor != None )
                                {
                                             if ( Instigator.InCurrentCombo() )
                                                          Possessor.Adrenaline = 0;
                                             Possessor.UnPossess();
                                             Instigator.SetOwner(TestController); // type mismatch error here when compiling
                                             Instigator.PlayerReplicationInfo = TestController.PlayerReplicationInfo;
                                             TestController.Possess(Warhead);
                                }
                                Warhead.Velocity = Warhead.AirSpeed * Vector(Warhead.Rotation);
                                Warhead.Acceleration = Warhead.Velocity;
                                WarHead.MyTeam = Possessor.PlayerReplicationInfo.Team;
                   }
                   else 
                   {
                                Weapon.Spawn(class'SmallRedeemerExplosion');
                                Weapon.HurtRadius(500, 400, class'DamTypeRedeemer', 100000, Instigator.Location);
                   }
      
                   bIsFiring = false;
                   StopFiring();
                   return None;
      }
      As I noted above, it gives me a type mismatch error when I compile on the line where I try to pass my custom controller class as a parameter to SetOwner(). From this and the code I pasted in my original post, it should be obvious that I do not understand pawns and their controllers. I need someone to explain what I am doing wrong and how to fix it. :/

      ViewTarget is basically all I had time to test tonight. I’ll get back to you on the rest as soon as I can.

      Comment


        #4
        If you only need to steer the missile, then you really do not need to actually possess it. The Unreal4Ever Tournament mod had a missile launcher (Tomahawk?) that just used the player's rotation (grabbing it through weapontick or something on the server) and had the missile rotation match that for the primary fire along with a little window on screen (alt fire was pretty much the same as the guided redeemer).

        You can sort of get the x and y size of a level by iterating through all navigation points (pathnodes) and keeping a list of the four with the largest and smallest x and y values, z values don't help much as they will all be next to walkable surfaces (with the exception of flying pathnodes). Another (painful) option would be to make a large configuration table that lists each map name and the vector where the predator would spawn. Then at level startup, the predator would simply search through the entire map list and if the map name was found, use the previously assigned vector as the starting point. Of course this requires you to go through each and every default level (nevermind custom ones) to pick out the "center point" to spawn the predator. If the map was mot found, just have it leave a log message to remind you to add a point later (or better yet create an exec command that allows you to simply set the point automatically after you fly to the desired center point before the match begins while spectating).

        On a side note the "ViewBot" console command allows you to iterate through the bots, "viewself" returns your view to your own pawn. The viewbot command along with the "showdebug" commands helps alot when debugging AI stuff. The "viewclass <classname>" also allows you to see from a selected actor.

        Comment


          #5
          I hate when real life gets in the way, lol. I haven’t had a lot of time to work on this, and I won’t for a while to come (finals), but I did have some. Anyway,

          Yeah, going through each map and assigning it a spawn point for the Predator would be extremely painful. It really is out of the question, since I would like to be able to handle custom maps along with the default ones. Going through the navigation points and holding onto the largest and smallest x and y values is something I had not considered, probably because I’d have no idea how to do it, lol. I was thinking about spawning an actual Predator and having it fly above the map. That’s something I still have to figure out how to do. But, I would want the size and shape of the Predator’s flight path to scale to the size and shape of the level. There is a huge difference between, say, DM-Morpheus3 and ONS-RedPlanet or ONS-Severence. The flight path for Morpheus3 would not suffice for either, and so I should definitely determine how to trace through the navigation points.

          As for guiding the missile down, I guess that stealing the player’s rotation would do the trick, but won’t the player still be able to move/look/fire even as his view is that of an entirely different target? I mean, it’d look a little ridiculous if, while the player is supposed to be steering the missile from a laptop, he’s instead spinning in circles looking at the floor. I can imagine another character coming up to him and saying “…dude, wtf, you drop a quarter or something?” Anyway, I would still like to learn how to swap controllers. I’ve been wanting to implement a 2x zoom feature, as opposed to whatever magnification the sniper rifles have, and some of that code is in the PlayerController class as I recall. I also intend at some point to implement a sprint mechanic, which I believe would also require overriding PlayerController and switching to my custom controller.

          Finally, with regards to pitch, I tried overriding the LimitPitch function in my missile class (the one that is descended from RedeemerWarhead and therefore Pawn) to simply return the pitch value it is passed, but that seemingly had no effect. In addition I modified the PitchUpLimit and PitchDownLimit values, but that also did not accomplish anything. I’m sorry, but I’m still relatively new to this and I fear I missed something obvious. I’m wondering what that might be.

          Comment


            #6
            1. Iterating through navigation points is pretty simple. Here is an example that I use in my UT Style Domination and Halo style King of the Hill gametypes to add all navigation points to a list (so I can randomly select from it later):
            Code:
            var array<NavigationPoint> NP;
            ....
                 forEach AllActors( class'NavigationPoint', N )
                    if ( !N.taken && FlyingPathNode(N)==none ){ //only use grounded path nodes and those that will not be spawned into
                        NP[i] = N;
                        i++;
                        NP.Insert(i,1);
                    }
            You could do a maximum and minimum comparison in there (check the N.location.X and N.location.Y values), but of course this does not really help to tell whether the center area has any visible "sky". Checking nearby path nodes for sufficient vertical clearance would probably be best. I would personally try to adapt the code from the bomber run or ion cannon and just force the player to only use the weapon when they have sufficient overhead clearance under the guise of "only being able to communicate with the predator when having an unobstructed view".

            Since UT2k4 does not use screen blurring based on distance, you could also just scale the size of the predator itself to simulate distance based on the space available.

            2. I would say just duplicate/modify the redeemer code for swapping the pawn owned by the controller (or course read and understand the code, but don't reinvent the wheel if the system works, and more importantly is known to work in network games). And, even if the player spinning around looked funny (if only the view were switched) don't ever underestimate the importance of giving up some realism to keep things simple and netgame compliant! (after all the spinny thing would only be an issue if playing the game with others).

            3. I have a sprint feature in my YARM mod (combination of the GoW roadie run and Call of Duty 4 style sprint) which was done with a custom pawn, a custom palyercontroller should work too (though no bot support then). Ballistic weapons was able to add a sprint feature using a custom inventory item I think (which would probably make your mutator more compatible with other mutators/gametypes). Make sure that ground speed changes are only done on the server (Role==ROLE_Authority) because I seem to recall that the cheat protection checks for clientside adjustments to groundspeed (speedhack detected).

            4. For pitch, take a careful look through the RedeemerWarhead code and what happens to the playercontroller in the PostNetBeginPlay function (specifically what state it is sent to), then follow that code in the playercontroller, it will show you how the controller's rotation is set (you will have to modify another function in your guided missile code).

            Comment


              #7
              I was actually thinking about MW2 killstreaks the other day.The AC130 would be awesome too.

              Also, I have a explosion effect that looks like the Predator missile you might be able to use.

              Comment


                #8
                Was the AC-130 controllable from the laptop computer? and what type of attacks did it have?

                Comment


                  #9
                  Yes, the AC-130 is a massive gunship controllable from the laptop. It has a machine gun, a medium-sized cannon, and a large cannon that has a long reload time in between shots. I agree, Herr General, it would be a pretty awesome mod, and I may begin work on it in parallel to the Predator, but to reproduce it faithfully will likely be outside the realm of my abilities for some time to come. Indeed, meowcat, I’m having trouble identifying the code of which you spoke in the PlayerController class. I followed the PostNetBeginPlay() function in RedeemerWarhead to the PlayerRocketing state in PlayerController, but I still don’t understand how it modifies pitch. Let me know if I’m hot or cold: Am I supposed to be looking at the call to UpdateRocketAcceleration()? I haven’t yet tried to decipher that wall of code in RedeemerWarhead, and I really don’t want to if I don’t have to, lol.

                  I’m having other problems aside from pitch. I have yet to experience any luck in my experiments to swap controllers for the guided warhead. meowcat, if you could, would you take another look at the second block of code in my second post? The one from the SpawnProjectile() function in RedeemerGuidedFire? I added comments on the line where I’m getting type mismatch errors. I’ve tried it in various ways, but it just won’t work. Another piece of code that just won’t work for me is one in which I try to shake the player’s view immediately after pressing the fire button to boost while guiding the missile. I’ve tried both ViewShake() and ShakeView() (the latter of which is actually used by RedeemerWarhead when the missile detonates to shake the views of all players in the vicinity of the blast), but neither seems to have any effect.

                  Finally, I have a somewhat more mundane request. Could you look at the following code and tell me why the compiler is saying I’m missing a ‘)’ on the line where I left a comment? I can’t for the life of me figure it out. (This code is just a basic test of spawning actors at all appropriate navigation points, using the code you supplied. I want to spawn crystals here later, which will supposedly be Tiberium deposits from the Command and Conquer universe. These nodes will be used in conjunction with the “Tiberium Blaster,” a weapon that depletes the nodes with its secondary fire to power its primary fire.)

                  Code:
                      local int i;
                      local NavigationPoint N;
                      local vector myVect;
                  
                      forEach AllActors(class'NavigationPoint', N)
                      {
                          if (!N.taken && FlyingPathNode(N) == none)
                          {
                              NP[i] = N;
                              i++;
                              NP.Insert(i,1);
                          }
                      }
                  
                      for (i = 0; i < NP.length; i++)
                      {
                          myVect = (NP[i].Location.X, NP[i].Location.Y, NP[i].Location.Z + 250); // missing ')' on this line, supposedly
                          spawn(class'ShockRiflePickup',,, myVect, NP[i].Rotation);
                      }

                  Comment


                    #10
                    For Pitch, yes the UpdateRocketAcceleration function adjusts the Pawn's (Warhead) pitch, which is what the controller's pitch (actually entire rotation) is set to in the PlayerMove function in the player rocketing state. To adjust this you will have to fiddle with the code prior to the line "SetRotation(rotator(Velocity));" in the UpdateRocketAcceleration function (my recommendation is the save the magnitude of the velocity vector in a local float, normalize the velocity vector, clamp the z component to an acceptable range (the "opposite" side of a right triangle with the hypotenuse being of length 1), renormalize the vector (since you just clamped the z value, you need to reset its magnitude to 1), multiply it by the saved magnitude (restore the overall speed), set the velocity to this adjusted velocity, then leave the setrotation line as is).

                    I'll see if I can pick anything out from the swap controller code. Will edit this post if I see anything obvious (I have little to no experience swapping controllers though so I might not spot anything...) [EDIT] Ok, the problem is that you never actually spawn a PredatorController object (so the TestController variable, a pointer of sorts in reality, is always evaluates/points to none/nothing). What is the purpose of the TestController?

                    I if recall correctly, that syntax can't be used for assigning vector values (though it is almost correct for default properties). Try this instead:
                    Code:
                    myVect = NP[i].Location;
                    myVect.Z += 250;

                    Comment


                      #11
                      Bah, I’m still struggling to find the time to script in between studying for finals (that and playing Modern Warfare 2, lol). Anyway, I’ll be glad when Monday rolls around, when I’m done with my last final.

                      meowcat, your advice worked, and it was quite amusing – the entire map was covered in floating Shock Rifles. XD I’ve made a number of changes since then. They’re now Flak Cannons with ambient light at ground height, with collision cylinders. I’ve also made the mutator an arena mutator for the Tiberium Blaster, which I have likewise implemented. The Tiberium Blaster has the primary fire of a Shock Rifle, but with a ludicrous fire rate and some spread. The secondary fire is that of a Link Gun. It is capable of destroying the Tiberium nodes, but getting it to augment ammo count upon consumption of a node and having the nodes respawn eventually is proving a little tricky.

                      Controllers are also still giving me problems. Below is code from my initial post. I touched it up a little, but it still throws me into spectator mode while my character stands around blankly. meowcat, I know you said you don’t have much experience swapping controllers, so I’ll ask this more generally: Does anyone have any idea what I could be missing?

                      Code:
                       var TestController newC;
                      
                      event PreBeginPlay()
                      {
                      	SetTimer(10, false);
                      }
                      
                      function Timer()
                      {
                      	local Controller C;
                      	local Pawn P;
                      
                      	for (C = Level.ControllerList; C != None; C = C.NextController)
                      	{
                      		newC = spawn(class'TestController');
                      
                      		P = C.Pawn;
                      		C.Unpossess();
                      		newC.Possess(P);
                      	}
                      }
                      As for the Predator’s pitch, well, yikes, that sounds complicated! I think I’ll leave it alone for now and move on to a more general thread (whose creation may have to wait a bit, because of finals), where I can ask questions on a myriad of topics, from my Command and Conquer mod to a three-burst Halo-esque Battle Rifle to remapping the Adrenaline combo controls. Don’t worry, I’ll come back to this at a later date, in one form or another. I won’t let your responses go to waste, meowcat.

                      Comment


                        #12
                        No problem. I may get around to adding a predator drone to my YARM mutator later anyways (to go along with my cheap knockoff COD4 mutator). I also have the Halo battle rifle (my remake of it anyways) in YARM (see my signature below). As for a command and conquer mod take a search around for the Unreal Annihilation mod, which was an RTS mod for UT2k4.

                        And a note for the above code, I'm not quite sure what that is supposed to do, but you would basically iterate through all the level's controllers, spawning a new test controller each time and assigning it to the controller's pawn (to include bots).

                        Comment


                          #13
                          The code in my last post is part of a test mutator that sets a timer in PreBeginPlay(). The timer basically attempts to do exactly what you said. It iterates through the level’s controller list and tries detaching the pawns from their controllers, spawning a test controller and trying to have that take possession of the newly freed pawn each iteration of the loop. I bother with a timer here as a solution to the problem of not having actual controllers on the level until after the match officially starts. I admit this is a really crappy solution, and indeed my follow up question after I got this working would be how to make this all happen seamlessly at match start, but for testing purposes this has done its job well enough. But I don’t know, the controller swap refuses to work; I’m missing some subtlety or other here.

                          Anyway, I’ll take a good look at your YARM mod, as well as Unreal Annihilation. I didn’t know there was an RTS mod for UT2004 (though I probably should have guessed). It should be fun. ^_^

                          Comment


                            #14
                            Originally posted by Premonition2035 View Post
                            I didn’t know there was an RTS mod for UT2004 (though I probably should have guessed). It should be fun. ^_^
                            You might also want to take a look at Command and Skaarj, which isn't a total conversation but just a gametype.

                            Comment

                            Working...
                            X