pressure1441
Sorceror
List<Server.StaticTile> list = new List<Server.StaticTile>();
List<StaticTile> eable = m.GetTilesAt(point, false, false, true);
using System;
using Server.Misc;
using Server.Items;
using Server.Targeting;
using System.Collections.Generic;
using Server.Regions;
using Server.Mobiles;
using Server.Network;
using Server.Items;
namespace Server.Horde
{
//The center of the Horde territory
public abstract class HordeSpawner :Item
{
#region Thieves types
/// <summary>
/// Here you can add more slots, if you want Hordes that mix more critters together...
/// but change also CreateThieves()...
/// </summary>
//Which critters in that horde ?
public virtual Type Type_1{ get{ return null; } }
public virtual Type Type_2{ get{ return null; } }
public virtual Type Type_3{ get{ return null; } }
//Ratio for distributing different types in our population
//Here we got 50% for the first, and 25% for each of the others
public virtual double Type_1_ratio{ get{ return 0.5; } }
public virtual double Type_2_ratio{ get{ return 0.5; } }
public virtual double Type_3_ratio{ get{ return 1.0; } }
#endregion
#region Constants
//How much thieves in the Horde ?
public virtual int m_minCount{ get{ return 3; } }
public virtual int m_maxCount{ get{ return 12; } }
//The whole territory size
public virtual int m_HordeHomeRange{ get{ return 200; } }
//The ambush area
public virtual int m_ThiefHomeRange{ get{ return 8; } }
//After a battle, they go away for a new one, but take their time
public virtual TimeSpan m_HordeSpawnDelay{ get{ return TimeSpan.FromMinutes(15);} }
//How long does they stay on the battle area, before go to do another ambush ?
public virtual TimeSpan m_VanishAfterCombat{ get{ return TimeSpan.FromMinutes(3);} }
public virtual bool AlwaysInForest{ get{ return true; } }
public virtual bool AlwaysNearARoad{ get{ return true; } }
public virtual bool ShowNames{ get{ return false; } }
#endregion
#region Variables
//Datetime before new ambush, cf m_HordeSpawnDelay
public DateTime NextSpawn;
//Our thieves
private List<Mobile> m_Thieves = new List<Mobile>();
//Who hurts our thieves
public List<Mobile> m_Attackers = new List<Mobile>();
//Where is the ambush, somewhere in range, cf m_HordeHomeRange
private Point3D m_CurrentLocation;
//Our treasure
public Item TreasureBag;
//the first to rummage a corpse call the others
public Mobile Rummager;
#endregion
#region HordeConstructor
public HordeSpawner() : base( 0x1f13 )
{
Visible = false;
Movable = false;
Name = "Horde Spawner";
Timer.DelayCall(TimeSpan.FromSeconds(2.0), new TimerCallback(Begin));
}
public void Begin()
{
TryGetSpawnPosition();
InitHorde();
CreateTreasureBag();
LaunchHorde();
}
#endregion
#region HordeSpawn
/// <summary>
/// Here we try to get a location, in a forest, near a road
/// </summary>
private void TryGetSpawnPosition()
{
// Try 100 times to find a Spawnable location.
for ( int i = 0; i < 100; i++ )
{
m_CurrentLocation = GetSpawnPosition(Map, Location, m_HordeHomeRange);
if(IsValidPosition(m_CurrentLocation))
break;
}
if(m_CurrentLocation == Location)
Timer.DelayCall(TimeSpan.FromSeconds(2.0), new TimerCallback(NoPossibleSpawn));
}
private Point3D GetSpawnPosition(Map map, Point3D loc, int m_HomeRange)
{
if ( map == null )
return loc;
// Try 10 times to find a Spawnable location.
for ( int i = 0; i < 10; i++ )
{
int x = loc.X + (Utility.Random( (m_HomeRange * 2) + 1 ) - m_HomeRange);
int y = loc.Y + (Utility.Random( (m_HomeRange * 2) + 1 ) - m_HomeRange);
int z = map.GetAverageZ( x, y );
if ( map.CanSpawnMobile( new Point2D( x, y ), this.Z ) )
return new Point3D( x, y, this.Z );
else if ( map.CanSpawnMobile( new Point2D( x, y ), z ) )
return new Point3D( x, y, z );
}
return loc;
}
private bool IsValidPosition(Point3D loc)
{
if(loc == Location)
return false;
if(CheckRegion(loc) && IsNextAForest(loc) && IsNearARoad(loc, 20))
return true;
m_CurrentLocation = Location;
return false;
}
private bool CheckRegion(Point3D loc)
{
Map map = Map;
if ( map == null )
return false;
Region reg = Region.Find(loc, map);
if(reg is GuardedRegion || reg is DungeonRegion || reg is HouseRegion)
return false;
return true;
}
private bool IsNextAForest(Point3D loc)
{
if(!AlwaysInForest)return true;
List<int> statics = GetStaticsInRange(loc, m_ThiefHomeRange, this.Map);
return FindTrees(statics);
}
public static List<int> GetStaticsInRange(Point3D p3d, int range, Map m)
{
Point2D p = new Point2D(p3d.X,p3d.Y);
List<int> result = new List<int>();
Point2D point;
int BeginX = p.X - range;
int BeginY = p.Y - range;
int EndX = p.X + range;
int EndY = p.Y + range;
for (int x = BeginX; x <= EndX; x++)
{
for (int y = BeginY; y <= EndY; y++)
{
point = new Point2D(x, y);
List<StaticTile> eable = m.GetTilesAt(point, false, false, true);
foreach (StaticTile t in eable)
{
result.Add(t.ID);
}
}
}
return result;
}
private bool FindTrees(List<int> statics)
{
int trees = 0;
for(int i=0;i<30;i++)
{
if(FindTree(statics))
trees++;
}
return trees >= 5;
}
private bool FindTree(List<int> statics)
{
for ( int i=0;i<statics.Count;i++ )
{
if(IsTree(statics[i]))
return true;
}
return false;
}
private static bool IsTree(int id)
{
for(int i=0;i<m_TreeTiles.Length;i++)
{
if(m_TreeTiles[i]==id)
return true;
}
return false;
}
private static int[] m_TreeTiles = new int[]
{
0x4CCA, 0x4CCB, 0x4CCC, 0x4CCD, 0x4CD0, 0x4CD3, 0x4CD6, 0x4CD8,
0x4CDA, 0x4CDD, 0x4CE0, 0x4CE3, 0x4CE6, 0x4CF8, 0x4CFB, 0x4CFE,
0x4D01, 0x4D41, 0x4D42, 0x4D43, 0x4D44, 0x4D57, 0x4D58, 0x4D59,
0x4D5A, 0x4D5B, 0x4D6E, 0x4D6F, 0x4D70, 0x4D71, 0x4D72, 0x4D84,
0x4D85, 0x4D86, 0x52B5, 0x52B6, 0x52B7, 0x52B8, 0x52B9, 0x52BA,
0x52BB, 0x52BC, 0x52BD,
0x4CCE, 0x4CCF, 0x4CD1, 0x4CD2, 0x4CD4, 0x4CD5, 0x4CD7, 0x4CD9,
0x4CDB, 0x4CDC, 0x4CDE, 0x4CDF, 0x4CE1, 0x4CE2, 0x4CE4, 0x4CE5,
0x4CE7, 0x4CE8, 0x4CF9, 0x4CFA, 0x4CFC, 0x4CFD, 0x4CFF, 0x4D00,
0x4D02, 0x4D03, 0x4D45, 0x4D46, 0x4D47, 0x4D48, 0x4D49, 0x4D4A,
0x4D4B, 0x4D4C, 0x4D4D, 0x4D4E, 0x4D4F, 0x4D50, 0x4D51, 0x4D52,
0x4D53, 0x4D5C, 0x4D5D, 0x4D5E, 0x4D5F, 0x4D60, 0x4D61, 0x4D62,
0x4D63, 0x4D64, 0x4D65, 0x4D66, 0x4D67, 0x4D68, 0x4D69, 0x4D73,
0x4D74, 0x4D75, 0x4D76, 0x4D77, 0x4D78, 0x4D79, 0x4D7A, 0x4D7B,
0x4D7C, 0x4D7D, 0x4D7E, 0x4D7F, 0x4D87, 0x4D88, 0x4D89, 0x4D8A,
0x4D8B, 0x4D8C, 0x4D8D, 0x4D8E, 0x4D8F, 0x4D90, 0x4D95, 0x4D96,
0x4D97, 0x4D99, 0x4D9A, 0x4D9B, 0x4D9D, 0x4D9E, 0x4D9F, 0x4DA1,
0x4DA2, 0x4DA3, 0x4DA5, 0x4DA6, 0x4DA7, 0x4DA9, 0x4DAA, 0x4DAB,
0x52BE, 0x52BF, 0x52C0, 0x52C1, 0x52C2, 0x52C3, 0x52C4, 0x52C5,
0x52C6, 0x52C7
};
private bool IsNearARoad(Point3D loc, int m_HomeRange)
{
if(!AlwaysNearARoad)return true;
for(int i=0;i<30;i++)
{
int x = loc.X + (Utility.Random( (m_HomeRange * 2) + 1 ) - m_HomeRange);
int y = loc.Y + (Utility.Random( (m_HomeRange * 2) + 1 ) - m_HomeRange);
StaticTile landTile = this.Map.Tiles.GetLandTile( x, y );
if(IsRoad(landTile.ID))
return true;
}
return false;
}
//Maybe sometimes it will not be a road, still be dirt
private bool IsRoad(int id)
{
for(int i=0;i<m_RoadTiles.Length;i++)
{
if(m_RoadTiles[i]==id)
return true;
}
return false;
}
//Seems don't need more tiles ID to work, but there's a lot missing
private static int[] m_RoadTiles = new int[]
{
0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78
};
//What else to do ?
private void NoPossibleSpawn()
{
Delete();
}
#endregion
#region HordeCreate
private void InitHorde()
{
for(int i=0;i<GetCount();i++)
{
m_Thieves.Add(CreateThieves());
}
}
private int GetCount()
{
return Utility.RandomMinMax(m_minCount, m_maxCount);
}
private Mobile CreateThieves()
{
//Initialize with a default value
Type ThiefType = Type_1;
if(Utility.RandomDouble() > Type_1_ratio)
ThiefType = Type_1;
else if(Utility.RandomDouble() > Type_2_ratio)
ThiefType = Type_2;
else if(Utility.RandomDouble() > Type_3_ratio)
ThiefType = Type_3;
BaseHordeThief result = (BaseHordeThief) Activator.CreateInstance(ThiefType);
result.Horde = this;
//result.Home = m_CurrentLocation;
return (Mobile)result;
}
private void LaunchHorde()
{
Map map = Map;
if(map == null)
return;
foreach(Mobile thief in m_Thieves)
{
SpawnThief(thief);
}
}
private void SpawnThief(Mobile thief)
{
if(thief != null && !thief.Deleted && thief.Alive)
{
((BaseHordeThief)thief).Hide();
Point3D loc = GetSpawnPosition(Map, m_CurrentLocation, m_ThiefHomeRange);
//thief.OnBeforeSpawn( loc, Map );
thief.MoveToWorld( loc, Map );
//thief.OnAfterSpawn();
}
}
#endregion
#region HordeActions
//An action begin
//Rummage and goaway does only happen if !InAction
private bool m_InAction;
public bool InAction
{
get{ return m_InAction;}
set{ m_InAction = value;
if(value==true)
{
//Good place to initilize it
CalledToRummage=false;
Rummager=null;
//rats wont go, as a new action begin
if(GoAway!=null)
GoAway.Stop();
}
}
}
//A thief see a player, all thieves are called
public void Call(Mobile m)
{
if(!InAction && m!=null && !m.Deleted && m.Alive)
{
if(!m_Attackers.Contains(m))
m_Attackers.Add(m);
InAction = true;
foreach(Mobile thief in m_Thieves)
{
if(thief != null && !thief.Deleted && thief.Alive)
((BaseHordeThief)thief).Unhide(m);
}
}
}
//Check for players, in order to stop or not the action
public void CheckAttackers(Mobile thief)
{
if(InAction)
{
Mobile combatant = thief.Combatant;
if(combatant!=null && !m_Attackers.Contains(combatant))
m_Attackers.Add(combatant);
List<Mobile> todelete = new List<Mobile>();
foreach(Mobile attacker in m_Attackers)
{
if(!attacker.Alive || !InLOS(attacker))
todelete.Add(attacker);
}
for(int i=0;i<todelete.Count;i++)
{
if(m_Attackers.Contains(todelete[i]))
m_Attackers.Remove(todelete[i]);
}
if( m_Attackers.Count<1 )
{
InAction = false;
GoAway = new GoAwayTimer(this);
GoAway.Start();
}
}
}
//they work together
private bool InLOS(Mobile mob)
{
bool see = false;
if(mob != null)
{
foreach(Mobile thief in m_Thieves)
{
if(thief != null && !thief.Deleted &&thief.Alive && thief.InLOS(mob))
{
see = true;
break;
}
}
}
return see;
}
//TimeSpan m_VanishAfterCombat and then Go away
//Timer will stop if InAction set to true
private Timer GoAway;
private class GoAwayTimer : Timer
{
private HordeSpawner Horde;
public GoAwayTimer(HordeSpawner horde) : base(horde.m_VanishAfterCombat)
{
Horde = horde;
}
protected override void OnTick()
{
Horde.EndAction();
}
}
private void EndAction()
{
if(!InAction)
{
CollectTreasure();
NextSpawn = DateTime.Now + m_HordeSpawnDelay;
m_Attackers = new List<Mobile>();
TryGetSpawnPosition();
LaunchHorde();
}
}
//Already called, don't send new calls
private bool CalledToRummage;
//All the rats may go to rummage the first looted corpse (player only)
public void CallToRummage(Mobile m)
{
if(!CalledToRummage && !InAction)
{
CalledToRummage = true;
Rummager = m;
m.CantWalk = true;
foreach(Mobile thief in m_Thieves)
{
if( thief != null && !thief.Deleted && thief.Alive && Utility.RandomBool())
{
(((BaseCreature)thief).AIObject).Action = ActionType.Interact;
}
}
}
}
#endregion
#region TreasureBag
private bool CreateTreasureBag()
{
TreasureBag = new Backpack();
foreach(Mobile thief in m_Thieves)
{
if(thief!=null && !thief.Deleted && thief.Alive)
{
thief.AddToBackpack(TreasureBag);
return true;
}
}
return false;
}
public void GiveTreasureBag(Mobile mob)
{
if(CheckTreasureBag())
{
if(TreasureBag.IsChildOf(mob.Backpack))
{
foreach(Mobile thief in m_Thieves)
{
if(thief!=null && thief!=mob && !thief.Deleted && thief.Alive)
{
thief.AddToBackpack(TreasureBag);
return;
}
}
}
}
}
private bool CheckTreasureBag()
{
if(TreasureBag!=null)
return true;
else return CreateTreasureBag();
}
private void CollectTreasure()
{
if(CheckTreasureBag())
{
foreach(Mobile thief in m_Thieves)
{
if(thief!=null && !thief.Deleted && thief.Alive)
{
foreach(Item item in ((BaseHordeThief)thief).Loots)
{
TreasureBag.AddItem(item);
}
((BaseHordeThief)thief).Loots = new List<Item>();
}
}
}
}
#endregion
#region HordeCleanUp
public override void OnDelete()
{
foreach(Mobile thief in m_Thieves)
{
thief.Delete();
}
base.OnDelete();
}
public void DeleteThief(Mobile mob)
{
//if(m_Thieves.Contains(mob))
// m_Thieves.Remove(mob);
}
#endregion
#region HordeSerialization
public HordeSpawner( Serial serial ) : base( serial )
{
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
int count = reader.ReadInt();
for(int i=0;i<count;i++)
{
m_Thieves.Add(reader.ReadMobile());
}
m_CurrentLocation = reader.ReadPoint3D();
TreasureBag = reader.ReadItem();
LaunchHorde();
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 1 ); // version
writer.Write( (int) m_Thieves.Count );
foreach(Mobile thief in m_Thieves)
{
writer.Write( (Mobile) thief );
}
writer.Write( (Point3D) m_CurrentLocation);
writer.Write( (Item) TreasureBag);
}
#endregion
}
public class BaseHordeThief : BaseCreature
{
#region Constructor
//A direct [add would find a null exception, cause of the missing Horde
//[Constructable]
public BaseHordeThief(AIType ai,
FightMode mode,
int iRangePerception,
int iRangeFight,
double dActiveSpeed,
double dPassiveSpeed)
: base(ai,
mode,
iRangePerception,
iRangeFight,
dActiveSpeed,
dPassiveSpeed ){}
//Our Horde
public HordeSpawner Horde;
//Without ShowNames, ambush is better
public override void OnAosSingleClick( Mobile from )
{
if(Horde.ShowNames)
base.OnAosSingleClick(from);
}
#endregion
#region Rummage
//they do rummage more than all others BaseCreatures
public override bool CanRummageCorpses{ get{ return true; } }
private const double ChanceToRummage = 1.0; // 100%
private const double MinutesToNextRummageMin = 0.0;
private const double MinutesToNextRummageMax = 1.0;
private const double MinutesToNextChanceMin = 0.10;
private const double MinutesToNextChanceMax = 0.10;
//all what our thief loot
public List<Item> Loots = new List<Item>();
//Same as base one
//but a little larger rummage-range (4 instead of 2)
//and make a CallToRummage, in order all the other rats came rummage too
//we also take a trace of looted items, in order to drop it later in our Treasure
//and toRummage extern to the method, in order to use it later
private Corpse toRummage = null;
public override bool Rummage()
{
toRummage = null;
foreach ( Item item in this.GetItemsInRange( 4 ) )//******
{
if ( item is Corpse && item.Items.Count > 0 )
{
toRummage = (Corpse)item;
break;
}
}
if ( toRummage == null )
return false;
else if(toRummage.Owner is PlayerMobile)
Horde.CallToRummage(this);//*******
Container pack = this.Backpack;
if ( pack == null )
return false;
List<Item> items = toRummage.Items;
bool rejected;
LRReason reason;
for ( int i = 0; i < items.Count; ++i )
{
Item item = items[Utility.Random( items.Count )];
Lift( item, item.Amount, out rejected, out reason );
if ( !rejected && Drop( this, new Point3D( -1, -1, 0 ) ) )
{
// *rummages through a corpse and takes an item*
PublicOverheadMessage( MessageType.Emote, 0x3B2, 1008086 );
if(toRummage.Owner is PlayerMobile)
Loots.Add(item);//********
return true;
}
}
return false;
}
//BaseAI.Interact does nothing, so it let us do our stuff
//It's called via CallToRummage
//Our rats run next the first one who loot a corpse
public override void OnActionInteract()
{
if(Horde.Rummager!=null)
{
if(Horde.Rummager==this)
{
this.MoveToWorld(toRummage.Location, Map);
}
else
this.AIObject.MoveTo( Horde.Rummager, true, 1 );
}
}
#endregion
#region Ambush
//You attack me, you attack the entire Horde
public override void OnCombatantChange()
{
if(Horde.Rummager==null)
Rummage();
Horde.CheckAttackers(this);
}
//Starts the ambush
public override void OnMovement( Mobile m, Point3D oldLocation )
{
if(m is PlayerMobile && m.Alive && m.AccessLevel==AccessLevel.Player && Horde.NextSpawn<DateTime.Now)
{
//A good place to initilize that
if(this.AIObject.Action == ActionType.Interact)
this.AIObject.Action = ActionType.Wander;
if(!Horde.InAction)
Horde.Call(m);
}
}
//Let's wait for a player
public void Hide()
{
Hidden = true;
CantWalk = true;
FocusMob = null;
}
//Attacking!!
public void Unhide(Mobile mob)
{
Hidden = false;
CantWalk = false;
if(mob!=null && !mob.Deleted && mob.Alive)
FocusMob = mob;
//if(this.FocusMob==null)
// this.AIObject.AcquireFocusMob( 20, this.FightMode, true, true, true );
}
#endregion
#region Kill
public override void Kill()
{
//The treasure still in the Horde till the end
Horde.GiveTreasureBag(this);
Horde.DeleteThief(this);
base.Kill();
}
#endregion
#region Serialization
public BaseHordeThief( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 );
writer.Write( (Item) Horde);
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
Horde = (HordeSpawner)reader.ReadItem();
}
#endregion
}
}
RunUO - [www.runuo.com] Version 2.1, Build 3995.28114
Core: Running on .NET Framework Version 2.0.50727
Core: Optimizing for 2 processors
Scripts: Compiling C# scripts...failed (1 errors, 0 warnings)
Errors:
+ Custom/HordeSystem.cs:
CS0117: Line 191: 'Server.Map' does not contain a definition for 'GetTilesAt
'
CS0029: Line 267: Cannot implicitly convert type 'Server.LandTile' to 'Serve
r.StaticTile'
Scripts: One or more scripts failed to compile or no script files were found.
- Press return to exit, or R to try again.
RunUO - [www.runuo.com] Version 2.1, Build 3995.28114
Core: Running on .NET Framework Version 2.0.50727
Core: Optimizing for 2 processors
Scripts: Compiling C# scripts...failed (1 errors, 0 warnings)
Errors:
+ Custom/HordeSystem.cs:
CS1525: Line 191: Invalid expression term '<'
CS1002: Line 191: ; expected
CS0029: Line 267: Cannot implicitly convert type 'Server.LandTile' to 'Serve
r.StaticTile'
Scripts: One or more scripts failed to compile or no script files were found.
- Press return to exit, or R to try again.
RunUO - [www.runuo.com] Version 2.1, Build 3995.28114
Core: Running on .NET Framework Version 2.0.50727
Core: Optimizing for 2 processors
Scripts: Compiling C# scripts...failed (1 errors, 0 warnings)
Errors:
+ Custom/HordeSystem.cs:
CS0103: Line 192: The name 'eable' does not exist in the current context
CS0246: Line 267: The type or namespace name 'Tile' could not be found (are
you missing a using directive or an assembly reference?)
Scripts: One or more scripts failed to compile or no script files were found.
- Press return to exit, or R to try again.