How UT2003 Weapons Work/Teaching Bots To Use Your Weapon
Overview
Bots don't understand the most obvious thing about your weapon. I don't care if it's just another machinegun or yet another shotgun. The truth is, it might as well be a stick of wood for all they care. Fortunatly, the bot does know how to pull a trigger, so it can handle that. Unfortunatly, it doesn't know what the trigger does or whether your superdoopershotgun is better than the wet noodle it can also choose from. Even if it can make a choice, there's probably more than one way to use your weapon, assuming there's an alt-fire function. This all means we're going to have to do a little work to make the weapon bot-friendly.
First, in any function you've got to get a handle for a bot. This is done like this:
local Bot B; B = Bot(Instigator.Controller);
And then running off and doing whatever we're going to do with it. I'm using examples from my work on the Mod Ideas/Semigib Onslaught mutator
Bot variables
- Pawn Enemy
- The pawn the bot is hunting/fighting with (not used normally since Target is the real meat)
- Actor Target
- Whatever the bot is shooting at
- bool bFire
- 1 if the primary fire mode is selected
- bool bAltFire
- 1 if the alt-fire mode is selected
Weapon Functions
- function float RangedAttackTime()
- Time for the bot to wait between attacks.
- function bool RecommendRangedAttack()
- Unknown, What is defined as "Ranged" in the UT engine? This is false by default, and ranged weapons don't seem to be bothered by this.
- function bool RecommendLongRangedAttack()
- Unknown, What is defined as "Long Ranged" in the UT engine? This is false by default, and ranged weapons don't seem to be bothered by this.
- function bool FocusOnLeader(bool bLeaderFiring)
- return true if the bot should focus on the leader of it's Squad. The best example of this is the Link Gun.
- function bool SplashDamage()
- return true if weapon effect has splash damage (if significant), used by bot to avoid hurting self. It should be based on current firing Mode if active
- function bool RecommendSplashDamage()
- return true if weapon should be fired to take advantage of splash damage. For example, rockets should be fired at enemy feet
- function float GetDamageRadius()
- return the damage radius of the splash damage.
- function float RefireRate()
- Repeater weapons like minigun should be 0.99, other weapons based on likelihood of firing again right away
- function bool FireOnRelease()
- tells AI that it needs to release the fire button for this weapon to do anything
- function byte BestMode()
- choose between regular or alt-fire, 0 is regular, 1 is alt-fire.
Note: This is for the Instagib Linkgun. The primary fire is only useful for other xPawns, and thus the secondary fire is chosen if the bot is targeting a xPawn. Of course, the primary fire doesn't help teammates, so the check for teams had to be added as well
function byte BestMode() { local bot B; B = Bot(Instigator.Controller); if (( B == None ) || ((xPawn(B.Target) != none) && (xPawn(B.Target).PlayerReplicationInfo.Team != Instigator.Controller.Pawn.PlayerReplicationInfo.Team))) return 0; return 1; }
- function bool BotFire(bool bFinished, optional name FiringMode)
- called by NPC firing weapon. Weapon chooses appropriate firing Mode to use (typically no change) bFinished should only be true if called from the Finished() function FiringMode can be passed in to specify a firing Mode (used by scripted sequences)
- simulated function float RateSelf()
- need to figure out modified rating based on enemy/tactical situation. The range is -2 to 2, the higher the better.
- function float GetAIRating()
- Returns the AI Rating for the weapon ranged from -2.0 to 2.0. This is the real meat of the rating system. It's what is used, along with a bot's personal opinion of the weapon (this is where the "favorite weapon" comes into play) comes into effect and is actually used when the bot trys to descide which weapon to bring up.
function float GetAIRating() { local Bot B; B = Bot(Instigator.Controller); if (B == None) return AIRating; if ( (B.Enemy == None) && (B.Target == none) && (AmmoCharge[0] >= FireMode[0].AmmoClass.default.AmmoAmount)) return -2.0; if (xPawn(B.Target) != none) return 2.0; if (Vehicle(B.Target) != none) return 1.2; if (VSize( Instigator.Location - B.Target.Location) > LinkFire(FireMode[1]).TraceRange) return -2.0; return AIRating; }
- function float SuggestAttackStyle()
- tells bot whether to charge or back off while using this weapon (negative = run away, positive = run towards)
- function float SuggestDefenseStyle()
- tells bot whether to charge or back off while defending against this weapon (negative = run away, positive = run towards)
- function bool SplashJump()
- return true if recommend jumping while firing to improve splash damage (by shooting at feet) true for R.L., for example
- function bool CanAttack(Actor Other)
- return false if out of range, can't see target, etc. otherwise, if the bot can attack then return true.
In this case, I had to let the bot know that the link beam has a limited range.
function bool CanAttack(Actor Other) { local bot B; B = Bot(Instigator.Controller); if (B == none) return true; if (( B.bAltFire == 1 ) && ( VSize( Instigator.Location - Other.Location) > LinkFire(FireMode[1]).TraceRange)) return false; return true; }
Comments
Enigmatic: OK, I probably could use a etter name/location for this mess, but I think it's a pretty solid block of something at least
JonAzz: What signifigance does this function have in any of this?
static function float GetRange() { if (default.LifeSpan == 0.0) return 15000; else return (default.MaxSpeed * default.LifeSpan); }
this is from UT2004... I can't find a UT2004 version, but I am assuming they are similar...somewhat.