Full Version : Make npcs go faster when damaged
xmlspawner >>XMLSpawner Mods and Tips >>Make npcs go faster when damaged


<< Prev | Next >>

Erica- 01-24-2007
Hi i am trying to make this guy move faster meaning he rides the horse normal but when his health down which means hes almost dead he runs but slow walking on the mount is there anyway to speed this up when his health almost down so would like him like running when almost dead heres the script
CODE
[Constructable]
 public MasterOfTheArts() : base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.175, 0.350 )
 {
  Name = "a master of the arts"; //the name players will see
  Body = 185; //how it look like in game
  BaseSoundID = 42; //what sound he makes (I still have problems with sound :(

  //ChampionSpawn = i_ChampionSpawn; //set if it spawn with champ spawn or normal spawn

  SetStr( 401, 420 ); //set stats
  SetDex( 81, 90 );
  SetInt( 201, 220 );

  SetHits( 1500, 1700 ); //set hp

  SetDamage( 50, 60 ); //set how much damage ~

  SetDamageType( ResistanceType.Physical, 50 ); //which damage type it does
  SetDamageType( ResistanceType.Poison, 50 );

  SetResistance( ResistanceType.Physical, 60, 80 ); //what resists it have
  SetResistance( ResistanceType.Fire, 55, 70 );
  SetResistance( ResistanceType.Cold, 55, 70 );
  SetResistance( ResistanceType.Poison, 55, 70 );
  SetResistance( ResistanceType.Energy, 55, 70 );

  SetSkill( SkillName.Anatomy, 120.0 );
  SetSkill( SkillName.Tactics, 120.0 );
  SetSkill( SkillName.Meditation, 120.0 );
  SetSkill( SkillName.Swords, 120.0 );
  SetSkill( SkillName.Wrestling, 120.0 );
  SetSkill( SkillName.Parry, 120.0 );
  SetSkill( SkillName.MagicResist, 120.0 );


  Fame = 30000; //its fame/karma
  Karma = -30000;
           
  VirtualArmor = 50;

  PlateChest chest = new PlateChest(); //add its armor and set its hue and not movable so it won't be on loot
  chest.Hue = 503;
  chest.Movable = false;
  AddItem( chest );
 
  PlateArms arms = new PlateArms();
  arms.Hue = 503;
  arms.Movable = false;
  AddItem( arms );
 
  PlateGloves gloves = new PlateGloves();
  gloves.Hue = 503;
  gloves.Movable = false;
  AddItem( gloves );
 
  PlateGorget gorget = new PlateGorget();
  gorget.Hue = 503;
  gorget.Movable = false;
  AddItem( gorget );
 
  PlateLegs legs = new PlateLegs();
  legs.Hue = 503;
  legs.Movable = false;
  AddItem( legs );
 
  AxeOfTheHeavens weapon = new AxeOfTheHeavens(); //add its weapon and set its hue and not movable so it won't be on loot
  //weapon.Name = "Crafting Union Leader's Hammer";
  weapon.Hue = 503;
  weapon.Movable = false;
  AddItem( weapon );
 
  FurBoots boots = new FurBoots(); //add its boots and set its hue and not movable so it won't be on loot
  boots.Hue = 503;
  boots.Movable = false;
  AddItem( boots );

  Item hair = new Item( 8251 );  //add its hair and set its hue and not movable so it won't be on loot
  hair.Hue = 503;
  hair.Layer = Layer.Hair;
  hair.Movable = false;
  AddItem( hair );

  AddItem( new Tokens( 500, 1000 ));
  //if ( Utility.Random(25) == 1 )
   //AddItem( new PersonalStatueDeed() );

  new IceSteed().Rider = this; //make it ride on mule
 }
 
 public void GiveCraftPowerScroll() //Generate power scroll routine and add to pack
 {
  List<Mobile> toGive = new List<Mobile>(); //no idea :(

  List<AggressorInfo> list = Aggressors; //I think it add list players that attacked it
  for ( int i = 0; i < list.Count; ++i )
  {
   AggressorInfo info = list[i];

   if ( info.Attacker.Player && info.Attacker.Alive && (DateTime.Now - info.LastCombatTime) < TimeSpan.FromSeconds( 30.0 ) && !toGive.Contains( info.Attacker ) )
    toGive.Add( info.Attacker );
  }

  list = Aggressed; //I think it add list of players it attacked
  for ( int i = 0; i < list.Count; ++i )
  {
   AggressorInfo info = list[i];

   if ( info.Defender.Player && info.Defender.Alive && (DateTime.Now - info.LastCombatTime) < TimeSpan.FromSeconds( 30.0 ) && !toGive.Contains( info.Defender ) )
    toGive.Add( info.Defender );
  }
  if ( toGive.Count == 0 )//if nobody attacked it and it didn't attack anybody then break operation and no ps MUAH
   return;

  // Randomize //absolutly no idea
  for ( int i = 0; i < toGive.Count; ++i )
  {
   int rand = Utility.Random( toGive.Count );
   Mobile hold = toGive[i];
   toGive[i] = toGive[rand];
   toGive[rand] = hold;
  }

  //PsCount = ChampionSpawn ? 5 : 2; //set how many ps to give if it spawned using champ spawn or normal spawn
  for ( int i = 0; i < 1; ++i ) //set to give 1 ps change the "< 1" to anything you want
  {
   Mobile m = (Mobile)toGive[i % toGive.Count];
   int level;
   double random = Utility.RandomDouble();
   if ( 0.2 >= random ) // select the level of the ps
    level = 120;
   else if ( 0.55 >= random )
    level = 115;
   else
    level = 110;
 
   //if ( Daat99OWLTR.Ops[5].Setting )
    //m.AddToBackpack( new ResourceRecipe() );
   
   switch ( Utility.Random( 13 )) // select which skill to use in the ps
   {
    case 0: m.AddToBackpack( new PowerScroll( SkillName.Blacksmith, level ) ); break; // give blacksmith ps acording to the ps level we selected before
    case 1: m.AddToBackpack( new PowerScroll( SkillName.Tailoring, level ) ); break;  
    case 2: m.AddToBackpack( new PowerScroll( SkillName.Tinkering, level ) ); break;
    case 3: m.AddToBackpack( new PowerScroll( SkillName.Mining, level ) ); break;  
    case 4: m.AddToBackpack( new PowerScroll( SkillName.Carpentry, level ) ); break;  
    case 5: m.AddToBackpack( new PowerScroll( SkillName.Alchemy, level ) ); break;
    case 6: m.AddToBackpack( new PowerScroll( SkillName.Fletching, level ) ); break;
    case 7: m.AddToBackpack( new PowerScroll( SkillName.Inscribe, level ) ); break;  
    case 8: m.AddToBackpack( new PowerScroll( SkillName.Cooking, level ) ); break;  
    case 9: m.AddToBackpack( new PowerScroll( SkillName.Cartography, level ) ); break;  
    case 10: m.AddToBackpack( new PowerScroll( SkillName.Lumberjacking, level ) ); break;
    case 11: m.AddToBackpack( new PowerScroll( SkillName.Lockpicking, level ) ); break;
    case 12: m.AddToBackpack( new PowerScroll( SkillName.Fishing, level ) ); break;
   }  
   m.SendLocalizedMessage( 1049524 ); // You have received a scroll of power!
  }
 }
 
 public override bool OnBeforeDeath( ) //what happens before it dies
 {
  IMount mount = this.Mount;
 
  if ( mount != null )
  {
   mount.Rider = null;
   
   if (mount is Mobile) ((Mobile)mount).Delete();
  }
 
 
  GiveCraftPowerScroll(); //call the generate ps routine
 
  switch (Utility.Random(3))
  {
   
    case 0: PackItem( new RunicSewingKit( CraftResource.SpinedLeather, 25 ) ); break;
    case 1: PackItem( new RunicSewingKit( CraftResource.HornedLeather, 25 ) ); break;
    case 2: PackItem( new RunicSewingKit( CraftResource.BarbedLeather, 25 ) ); break;
   
  }
  switch (Utility.Random(8))
  {
   
    case 0: PackItem( new DullCopperOre( 25 ) ); break;
    case 1: PackItem( new ShadowIronOre( 25 ) ); break;
    case 2: PackItem( new CopperOre( 25 ) ); break;
    case 3: PackItem( new BronzeOre( 25 ) ); break;
    case 4: PackItem( new GoldOre( 25 ) ); break;
    case 5: PackItem( new AgapiteOre( 25 ) ); break;
    case 6: PackItem( new VeriteOre( 25 ) ); break;
    case 7: PackItem( new ValoriteOre( 25 ) ); break;
  }
 
  switch ( Utility.Random( 8 ))
  {
   
   
    case 0: PackItem( new RunicHammer( CraftResource.DullCopper, 25 ) ); break;
    case 1: PackItem( new RunicHammer( CraftResource.ShadowIron, 25 ) ); break;
    case 2: PackItem( new RunicHammer( CraftResource.Copper, 25 ) ); break;
    case 3: PackItem( new RunicHammer( CraftResource.Bronze, 25 ) ); break;
    case 4: PackItem( new RunicHammer( CraftResource.Gold, 25 ) ); break;
    case 5: PackItem( new RunicHammer( CraftResource.Agapite, 25 ) ); break;
    case 6: PackItem( new RunicHammer( CraftResource.Verite, 25 ) ); break;
    case 7: PackItem( new RunicHammer( CraftResource.Valorite, 25 ) ); break;
   
    //case 9: PackItem( new RunicSewingKit( CraftResource.RegularLeather, 10 ) ); break; // normal leather runic sewing kit with 10 charges
    //case 10: PackItem( new RunicSewingKit( CraftResource.SpinedLeather, 10 ) ); break;
    //case 11: PackItem( new RunicSewingKit( CraftResource.HornedLeather, 10 ) ); break;
    //case 12: PackItem( new RunicSewingKit( CraftResource.BarbedLeather, 10 ) ); break;
   
  }
  return true;
 }
 
 public override bool BardImmune{ get{ return true; } } //make it bardimmune: unpeaceable\unprovokable\undiscorded
 public override bool AlwaysMurderer{ get{ return true; } } //make the npc red
 public override bool Unprovokable{ get{ return true; } }
 public override bool CanRummageCorpses{ get{ return true; } }
 
 public override bool AlwaysAttackable{ get{ return true; } }
 public override bool Uncalmable{ get{ return true; } }
 public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
 public override void GenerateLoot() //add normal loot
 {
  AddLoot( LootPack.SuperBoss, 2 ); // set the loot type to ultra rich
 }
 
 public MasterOfTheArts( Serial serial ) : base( serial ) // no idea what this does
 {
 }
 
 public override void Serialize( GenericWriter writer ) // this save the info on the mob so it won't be deleted all the time
 {
  base.Serialize( writer );
  writer.Write( (int) 0 ); // version
 }
 
 public override void Deserialize( GenericReader reader ) // this load the info on the mob so it won't be deleted all the time
 {
  base.Deserialize( reader );
  int version = reader.ReadInt();
 }
}
}



ArteGordon- 01-25-2007
the AI controls the speed of creatures when they are injured with the offset calculation in TransformMoveDelay in BaseAI.cs

What I would do would be to add a mod that lets you add an attachment to individual creatures to change their speed when damaged.
This mod would allow you to specify the speed factor with damage by using an XmlValue attachment named "DamagedSpeedFactor".
QUOTE

        public double TransformMoveDelay(double delay)
        {
            bool isPassive = (delay == m_Mobile.PassiveSpeed);
            bool isControlled = (m_Mobile.Controlled || m_Mobile.Summoned);

            if (delay == 0.2)
                delay = 0.3;
            else if (delay == 0.25)
                delay = 0.45;
            else if (delay == 0.3)
                delay = 0.6;
            else if (delay == 0.4)
                delay = 0.9;
            else if (delay == 0.5)
                delay = 1.05;
            else if (delay == 0.6)
                delay = 1.2;
            else if (delay == 0.8)
                delay = 1.5;

            if (isPassive)
                delay += 0.2;

            if (!isControlled)
            {
                delay += 0.1;
            }
            else if (m_Mobile.Controlled)
            {
                if (m_Mobile.ControlOrder == OrderType.Follow && m_Mobile.ControlTarget == m_Mobile.ControlMaster)
                    delay *= 0.5;

                delay -= 0.075;
            }

            // ARTEGORDONMOD
            // allow individual creatures to change the normal movement slowdown when damaged
            double speedfactor = 0.8;

            XmlValue a = (XmlValue)XmlAttach.FindAttachment(m_Mobile, typeof(XmlValue), "DamagedSpeedFactor");
            if (a != null)
            {
                speedfactor = (double)a.Value / 100.0;
            }

            // ARTEGORDONMOD
            // fix div by zero crash
            //double offset = (double)m_Mobile.Hits / m_Mobile.HitsMax;
            double offset = m_Mobile.HitsMax > 0 ? (double)m_Mobile.Hits / m_Mobile.HitsMax : 1;

            if (offset < 0.0)
                offset = 0.0;
            else if (offset > 1.0)
                offset = 1.0;

            offset = 1.0 - offset;

            delay += (offset * speedfactor);

            if (delay < 0.0)
                delay = 0.0;

            return delay;
        }


MasterOfTheArts/ATTACH/xmlvalue,DamagedSpeedFactor,80
would be the normal default

MasterOfTheArts/ATTACH/xmlvalue,DamagedSpeedFactor,10
would slow them down less

MasterOfTheArts/ATTACH/xmlvalue,DamagedSpeedFactor,0
would not change the speed at all when damaged

MasterOfTheArts/ATTACH/xmlvalue,DamagedSpeedFactor,-80
would actually speed them up with damage

you could also add the attachment directly in the constructor instead of in the spawner entry like
XmlAttach.AttachTo(this, new XmlValue("DamagedSpeedFactor", -80));

Note that you would also have to make sure that you added this to the top of the baseai.cs or your creature script

CODE

using Server.Engines.XmlSpawner2;