RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

[RunUO 1.0] Alambik's ARMY: UO Age Of Empire !?

alambik

Sorceror
[RunUO 1.0] Alambik's ARMY: UO Age Of Empire !?

SUMMARY:
This system allows to create an army by recruiting NPC and command them as a group of NPC thanks to a gump.

FEATURES:
- Available formations:
full square formation
empty square
triangle
circle
random (barbarians...)
- stay in formation, do not attack
- stay in formation, attack people in range: (if have range weapon with enough ammo, use it, else, only attack people in front of you)
- melee: attack a specific target
- free for all
- disband army
- no NPC number limitation
- formation can go on a targetted location
- formation can move in the 8th directions
- individual NPC can move in the 8th directions
- the army NPCs can say a sentence that the controler input
- only 1 controler is allowed to control an army (army owner property)
- if GM, you can recruit new NPC in the army
- can be army of mixed NPCs
- when a NPC is killed, the next order will re-arrange the formation to fill the place of the dead NPC.

SUPPORT
Absolutly no support.
Tested on 1.0 RunUO version.
A lot of enhancement are needed.
Provided as-is.
You are free to modify it and post new versions of the script.

INSTALATION

- Drag and drop the files of the archive into your custom RunUO 1.0 script folder
- Modify the BaseCreature.cs and BaseAI.cs of your initial RunUO 1.0 scripts file as follow:

MODIFICATIONS:

You have to add the army Artificial Intelligence possibility for all creature. This require some code to add:

A) Open the Engines\AI\AI\BaseAI.cs file:

You have to add the AI into the possible types:
REPLACE THIS:
Code:
		AI_Thief
	}
WITH THIS:
Code:
		AI_Thief
		///// ALAMBIK: ARMY SYSTEM /////
		,AI_Army
		///////////////////////////////////////
	}


B) Open the Engines\AI\Creature\Basecreature.cs file:


1) First, you have to :

REPLACE THIS
Code:
		private AIType	m_CurrentAI;			// The current AI
		private AIType	m_DefaultAI;			// The default AI

WITH THIS:
Code:
		private AIType	m_CurrentAI;			// The current AI
		private AIType	m_DefaultAI;			// The default AI
		///// ALAMBIK: ARMY SYSTEM /////////
		[CommandProperty( AccessLevel.GameMaster )]
		public AIType DefaultAI
		{ get{ return m_DefaultAI; } set{ m_DefaultAI = value; } }
		///////////////////////////////////////////

2) Thenm in the "ChangeAIType" function you have to

REPLACE THIS:
Code:
			switch (NewAI)
			{
				case AIType.AI_Melee:
					m_AI = new MeleeAI(this);
					break;

WITH THIS:
Code:
			switch (NewAI)
			{
				//// ALAMBIK: ARMY SYSTEM ////
				case AIType.AI_Army:
					m_AI = new ArmyAI(this);
					break;
				/////////////////////////////////////
				case AIType.AI_Melee:
					m_AI = new MeleeAI(this);
					break;
 

Pyro-Tech

Knight
wow...this is great idea.

I know you say no support, so i hope someone picks this one up....I can see this as a great way for guilds of small players actually able to wage a war :)

either way...thanks for releasing and good work
 

LordHogFred

Knight
Awesome, awesome and awesome.
Anyone had a look to see how "incompatible" with RUO 2.0 it is atm? Might see if I can get it to work :).
 

Liacs

Sorceror
it is VEEEEERYcompatible with runuo 2.0. the only things you have to change are the spelling mistakes like controled to controlled, aquired to acquired... I will post a runuo 2.0 version if Alambik doesn't mind.

But my question is: how to recruit the soldiers?

Thanks for your help.

Lia
 

Attachments

  • Army.rar
    8.1 KB · Views: 192

alambik

Sorceror
Add an armycontroler item.
Open gump by double clicking it.
Click the green button in bottom left of the gump to recruit. This button appears only for gamemasters or higher.
 

XenoNeo

Sorceror
Try this!

I went ahead and did a simple mod that may of be interest to you all!

ok, in Armycontroller.cs, Look for this section and add what is in blue; which in doing this should confirm who's men these are! Something I found that cleared confusion when in battles with other players that have the same type of npc as I do.
Code:
		public void Recruit(Mobile from, BaseCreature soldier)
		{
			if (!Soldiers.Contains(soldier))
			{
				Soldiers.Add(soldier);
				soldier.ChangeAIType(AIType.AI_Army);
				soldier.Controlled=false;
				soldier.ControlMaster=null;
[COLOR="RoyalBlue"]				soldier.Title=(""+ ((PlayerMobile)from).Name +"'s Guard");[/COLOR]
				from.SendMessage("La cible a été ajouté au groupe.");
				SetFormation(ArmyFormationEnum.Latest);
				SetDirection(m_ArmyDirection);
			} else{
				from.SendMessage("Select a creature to recruite in your army...");
			}
			TargetRecruit(from);
		}
 

CosmoSpira

Sorceror
wow, this is a great idea! cant wait to get home and try it out...I just have to survive work today...just a few more hours:(
 
CosmoSpira;666293 said:
wow, this is a great idea! cant wait to get home and try it out...I just have to survive work today...just a few more hours:(

Think i'll like it to with the gate system im using if i can fig out how to set this to only work on the fel side of things
 

Pyro-Tech

Knight
If the recruit button is only available to game master's, then how can players make use of this?? is there a way to allow a charge in gold per soldier recruited so that you can enable this for players??

Or am i misunderstanding the concept here?:confused:
 
That should be easy - 03-23-2007, 06:38 PM

--------------------------------------------------------------------------------

That should be easy...

if( map == map.Felucca )

Ya really and in which file would you think it need to be placed
 

Dramier

Wanderer
I took the liberty of translating the French parts to English...

I'm working on adding Player control as well.
 

Attachments

  • Army [English].rar
    8 KB · Views: 116

XenoNeo

Sorceror
I got a simple method i am working on now, so take a look:
Code:
using System;
using Server;
using Server.Mobiles;
using Server.Gumps;
using System.Collections;
using Server.Targeting;
using Server.Targets;
using Server.Network;
using Server.Engines.Help;
using Server.Prompts;


namespace Server.Items
{
	public enum ArmyFormationEnum
	{
		Latest,
		FullSquare,
		EmptySquare,
		Line,
		Triangle,
		Other,
		Bordel
	}

	public class ArmyController : Item
	{
	
		private Mobile m_Owner;
		[CommandProperty( AccessLevel.GameMaster )]
		public Mobile Owner { get{ return m_Owner; } set{ m_Owner = value; } }

		private bool m_War;
		[CommandProperty( AccessLevel.GameMaster )]
		public bool War { get{ return m_War; } set{ m_War = value; } }
		
		private bool m_Free;
		[CommandProperty( AccessLevel.GameMaster )]
		public bool Free { get{ return m_Free; } set{ m_Free = value; } }
		
		private Point3D m_ArmyHome;
		[CommandProperty( AccessLevel.GameMaster )]
		public Point3D ArmyHome { get{ return m_ArmyHome; } set{ m_ArmyHome = value; } }

		private Direction m_ArmyDirection;
		[CommandProperty( AccessLevel.GameMaster )]
		public Direction ArmyDirection { get{ return m_ArmyDirection; } set{ m_ArmyDirection = value; } }

		private Direction m_ArmyFormationDirection;
		[CommandProperty( AccessLevel.GameMaster )]
		public Direction ArmyFormationDirection { get{ return m_ArmyFormationDirection; } set{ m_ArmyFormationDirection = value; } }
		
		private ArmyFormationEnum m_CurrentFormation;
		[CommandProperty( AccessLevel.GameMaster )]
		public ArmyFormationEnum CurrentFormation { get{ return m_CurrentFormation; } set{ m_CurrentFormation = value; } }		

		private ArrayList Soldiers = new ArrayList();

		[Constructable]
		public ArmyController() : base( 3007 )
		{
			Weight = 0.0;
			Name = "Controleur d'Armee [HRP]";
			m_Owner = null;
			m_ArmyDirection=Direction.North;
			m_ArmyFormationDirection=Direction.North;
			m_ArmyDirection=Direction.North;
			m_CurrentFormation=ArmyFormationEnum.FullSquare;
		}

		public void GoThere(Point3D point)
		{
			m_ArmyHome=point;
			int xx=0;
			int yy=0;
			int x=0;
			int y=0;
			int a=0;
			int b=0;
			double c=0.0;
			a=Soldiers.Count;
			b=(int)Math.Sqrt((double)Soldiers.Count);
			c=((double)a)/6.292;			
			
			for(int i = 0; i<a; i++ )
			{
				BaseCreature soldier=(BaseCreature)Soldiers[i];
				switch(m_ArmyFormationDirection)
				{
					case Direction.North: xx=  x   ; yy=    y ;  break;
					case Direction.Right: xx=  x+y ; yy= -x+y ;  break;
					case Direction.East:  xx=    y ; yy= -x   ;  break;
					case Direction.Down:  xx= -x+y ; yy= -x-y ;  break;
					case Direction.South: xx=   -x ; yy= -y   ;  break;
					case Direction.Left:  xx= -x-y ; yy=  x-y ;  break;
					case Direction.West:  xx=   -y ; yy=  x   ;  break;
					case Direction.Up:    xx=  x-y ; yy=  x+y ;  break;
					default:                                     break;
				}
				if ( !(soldier.AIObject is ArmyAI) )
					soldier.ChangeAIType(AIType.AI_Army);
				((ArmyAI)(soldier.AIObject)).ArmyHome=new Point3D(point.X+xx,point.Y+yy,point.Z);
				switch(m_CurrentFormation)
				{
					case ArmyFormationEnum.Latest:
						break;
					case ArmyFormationEnum.FullSquare:
						if (x==0)
						{
							x=y+1;
							y=0;
						} else if (y<x) {
							y++;
						} else {
							x--;
						}
						break;
					case ArmyFormationEnum.EmptySquare:
						if ((x<a/4) && (y==0))
						{
							x=x+1;
						} else if ((x==a/4) && (y<a/4)) {
							y++;
						} else if ((x>0) && (y==a/4)) {
							x--;
						} else {
							y--;
						}
						break;
					case ArmyFormationEnum.Line:
						x++;
						break;
					case ArmyFormationEnum.Triangle:
						if (x==0)
						{
							x=y+1;
							y=0;
						} else {
							y=x;
							x=0;
						}
						break;
					case ArmyFormationEnum.Other:
						x=(int)((c+0.5)*Math.Cos((double)(i+1)/c)-(c+0.5));
						y=(int)((c+0.5)*Math.Sin((double)(i+1)/c));
						break;
					case ArmyFormationEnum.Bordel:
						{
							x=Utility.RandomMinMax(0,b*2);
							y=Utility.RandomMinMax(0,b*2);
						}
						break;
					default:
						break;
				}
			}
			CheckSoldiersStatus();
		}

		public void SetDirection(Direction direction)
		{
			m_ArmyDirection=direction;
			for(int i = Soldiers.Count-1; i>=0; i-- )
			{
				BaseCreature soldier=(BaseCreature)Soldiers[i];
				if ( soldier.Direction != m_ArmyDirection)
				{
					if ( !(soldier.AIObject is ArmyAI) )
						soldier.ChangeAIType(AIType.AI_Army);
					((ArmyAI)(soldier.AIObject)).ArmyDirection=m_ArmyDirection;
				}
			}
			UpdateAction();
		}
		
		public void Recruit(Mobile from, BaseCreature soldier)
		{
			[COLOR="Red"]if( soldier is BaseHire && !soldier.Controlled )[/COLOR]
			{
				if (!Soldiers.Contains(soldier))
				{
					Soldiers.Add(soldier);
					soldier.ChangeAIType(AIType.AI_Army);
[COLOR="Red"]					soldier.Controlled= true;
					soldier.ControlMaster= from;
					soldier.Title=(""+ ((PlayerMobile)from).Name +"'s Guard");[/COLOR]
					from.SendMessage("La cible a été ajouté au groupe.");
					SetFormation(ArmyFormationEnum.Latest);
					SetDirection(m_ArmyDirection);
				} 
				else
				{
					from.SendMessage("This must be used on a hireable NPC!");
				}
				TargetRecruit(from);
			}
			else
			{
				from.SendMessage( "Cannot hire that!" );
			}
		}

		public void Attack(Mobile from, Mobile mob)
		{
			for(int i = Soldiers.Count-1; i>=0; i-- )
			{
				BaseCreature soldier=(BaseCreature)Soldiers[i];
				if ( soldier.AIObject != null )
				{
					soldier.FocusMob = mob;
					soldier.Combatant = mob;
					soldier.FocusMob = null;
				}
			}
			m_Free=true;
			SetWar();
		}
		
		public void TargetGoTo(Mobile from)
		{
			CheckSoldiersStatus();
			from.SendMessage("Select a targeted area for your army to goto...");
			from.Target=new ArmyGoToTarget( this ); 
		}

		public void TargetAttack(Mobile from)
		{
			from.SendMessage("Select a creature/player for your army to attack...");
			from.Target=new ArmyAttackTarget( this ); 							
		}

		public void TargetRecruit(Mobile from)
		{
			from.SendMessage("Select a creature to recruit in your army...");
			from.Target=new ArmyRecruitTarget( this ); 							
		}

		public void SetFormation(ArmyFormationEnum formation)
		{
			m_Free=false;
			if (formation != ArmyFormationEnum.Latest)
			{
				if ( m_CurrentFormation == formation )
					m_ArmyFormationDirection= (Direction)((1+(int)m_ArmyFormationDirection) % 8);
				else
					m_CurrentFormation = formation;
				if (m_CurrentFormation == ArmyFormationEnum.Triangle)
					SetDirection((Direction)((7+(8-(int)m_ArmyFormationDirection)) % 8));
				else
					SetDirection((Direction)(((8-(int)m_ArmyFormationDirection)) % 8));
			}
			GoThere(m_ArmyHome);
			UpdateAction();
		}
		
		public void SetWar()
		{
			m_War=true;
			UpdateAction();
		}
		
		public void SetPeace()
		{
			m_War=false;
			UpdateAction();
		}

		public void SetFree()
		{
			m_Free=true;
			UpdateAction();
		}

		public void UpdateAction()
		{
		CheckSoldiersStatus();
			for(int i = Soldiers.Count-1; i>=0; i-- )
			{
				BaseCreature soldier=(BaseCreature)Soldiers[i];
				if (Free)
					if (m_War)
					{
						soldier.AIObject.Action = ActionType.Combat;
						if (soldier.AIObject is ArmyAI)
							((ArmyAI)(soldier.AIObject)).ArmyFightMode=FightMode.Closest;
						soldier.Team=Serial;
					}
					else
					{
						soldier.AIObject.Action = ActionType.Wander;
						if (soldier.AIObject is ArmyAI)
							((ArmyAI)(soldier.AIObject)).ArmyFightMode=FightMode.Aggressor;
						soldier.Team=0;
						soldier.Combatant=null;
					}
				else
					if (m_War)
					{
						soldier.AIObject.Action = ActionType.Guard;
						if (soldier.AIObject is ArmyAI)
							((ArmyAI)(soldier.AIObject)).ArmyFightMode=FightMode.Closest;
						soldier.Team=Serial;
					}
					else
					{
						soldier.AIObject.Action = ActionType.Backoff;
						if (soldier.AIObject is ArmyAI)
							((ArmyAI)(soldier.AIObject)).ArmyFightMode=FightMode.Aggressor;
						soldier.Team=0;
						soldier.Combatant=null;
					}
			}
		}

		public void Disband(bool toDelete)
		{
			for(int i = Soldiers.Count-1; i>=0; i-- )
			{
				BaseCreature soldier=(BaseCreature)Soldiers[i];
				soldier.ChangeAIToDefault();
				soldier.Controlled=false;
				soldier.ControlMaster=null;
				soldier.Title=("");
				soldier.Team=0;
				Soldiers.RemoveAt(i);
			}
			if (toDelete)
				Delete();
		}

		public void PromptSay(Mobile from)
		{
			from.SendMessage("Entrez la phrase à prononcer par le groupe:");
			from.Prompt = new ArmySayPrompt( this );
		}

		public void ArmySay(string text)
		{
			CheckSoldiersStatus();
			for ( int i = 0; i < Soldiers.Count; i++ )
			{
				if (Utility.RandomDouble() > 0.7)
					((BaseCreature)(Soldiers[i])).Say(text);
			}
		}

		public void CheckSoldiersStatus()
		{
			bool finnished=false;
			while (!finnished)
			{
				if (Soldiers.Count<=0)
					finnished=true;
				else
					for(int i = 0; i < Soldiers.Count; i++ )
					{
						BaseCreature soldier=(BaseCreature)Soldiers[i];
						if (soldier.Deleted || !(soldier.Alive))
						{
							Soldiers.RemoveAt(i);
							i=Soldiers.Count;
						} else {
							if (i >= Soldiers.Count-1)
								finnished=true;
						}
					}
			}
		}

		public override void OnDoubleClick( Mobile from )
		{
			if (from.AccessLevel>=AccessLevel.GameMaster)
				m_Owner = from;
			if (m_Owner == null)
			{
				from.SendMessage("This is not yours. The Item has been deleted.");
				if (m_Owner != null) m_Owner.SendMessage("{0} Tried to illegaly use an ArmyController.",from.Name);
				Delete();
				PageQueue.Enqueue( new PageEntry( from, "Ce Page a ete envoye par le server: ce joueur a essaye d'utiliser un ArmyControler qui n'etait pas le sien.", PageType.Other ) );
			} else {
				if (from == m_Owner)
				{
					from.SendGump(new ArmyGump(this));
				}
				else
				{
					from.SendMessage("This is not yours. The Item has been deleted.");
					if (m_Owner != null) m_Owner.SendMessage("{0} Tried to illegaly use an ArmyController.",from.Name);
					Delete();
					PageQueue.Enqueue( new PageEntry( from, "Ce Page a ete envoye par le server: ce joueur a essaye d'utiliser un ArmyControler qui n'etait pas le sien.", PageType.Other ) );
				}
			}
		}

		public override void OnDelete()
		{
			Disband(false);
			if (m_Owner != null)
				m_Owner.CloseGump(typeof(ArmyGump));
			base.OnDelete();
		}

		public ArmyController( Serial serial ) : base( serial )
		{
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );

			writer.Write( (int) 1 ); // version
			
			writer.Write( m_ArmyHome );
			writer.Write( m_Owner );
			writer.Write( m_War );
			writer.Write( m_Free );
			writer.Write( (int)m_ArmyDirection );
			writer.Write( (int)m_ArmyFormationDirection );			
			writer.Write( (int)m_CurrentFormation );
			writer.WriteMobileList( Soldiers );
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );

			int version = reader.ReadInt();
			
			switch (version)
			{
			case 1: 	
				m_ArmyHome= reader.ReadPoint3D();
				goto case 0;
			case 0:
				m_Owner = reader.ReadMobile();
				m_War = reader.ReadBool();
				m_Free = reader.ReadBool();
				m_ArmyDirection = (Direction)reader.ReadInt();
				m_ArmyFormationDirection = (Direction)reader.ReadInt();
				m_CurrentFormation = (ArmyFormationEnum)reader.ReadInt();
				Soldiers = reader.ReadMobileList();
				break;
			default:
				break;
			}			
		}
	}
	///////////////////////////////////////////////////
	public class ArmySayPrompt : Prompt
	{
		private ArmyController m_ArmyController;

		public ArmySayPrompt( ArmyController controller )
		{
			m_ArmyController = controller;
		}

		public override void OnResponse( Mobile from, string text )
		{
			if (  m_ArmyController != null)
			if ( !m_ArmyController.Deleted )
			if (  m_ArmyController.Owner != null )
			if (  m_ArmyController.Owner.Alive && !(m_ArmyController.Owner.Deleted) )
			if (  m_ArmyController.Owner == from )
				m_ArmyController.ArmySay(text);
		}
	}
	////////////////////////////////////////////////////
	public class ArmyGoToTarget : Target 
	{ 
		private ArmyController m_ArmyController;

		public ArmyGoToTarget( ArmyController controller ) : base ( -1, true, TargetFlags.None ) 
		{ 
         		m_ArmyController = controller; 
		} 

		protected override void OnTarget( Mobile from, object target ) 
		{
			if (  m_ArmyController != null)
			if ( !m_ArmyController.Deleted )
			if (  m_ArmyController.Owner != null )
			if (  m_ArmyController.Owner.Alive && !(m_ArmyController.Owner.Deleted) )
			if (  m_ArmyController.Owner == from )
			if ( target is IPoint3D)
			{
				IPoint3D p = target as IPoint3D;
				Point3D p3d = new Point3D(p);
				m_ArmyController.GoThere( p3d );
			}
		}
	}
	////////////////////////////////////////////////////
	public class ArmyRecruitTarget : Target 
	{ 
		private ArmyController m_ArmyController;

		public ArmyRecruitTarget( ArmyController controller ) : base ( -1, false, TargetFlags.None ) 
		{ 
         		m_ArmyController = controller; 
		} 

		protected override void OnTarget( Mobile from, object target ) 
		{
			if (  m_ArmyController != null)
			if ( !m_ArmyController.Deleted )
			if (  m_ArmyController.Owner != null )
			if (  m_ArmyController.Owner.Alive && !(m_ArmyController.Owner.Deleted) )
			if (  m_ArmyController.Owner == from )
			if ( target is BaseCreature)
			{
				m_ArmyController.Recruit( from, (BaseCreature)target );
			}
		}
	}
	////////////////////////////////////////////////////
	public class ArmyAttackTarget : Target 
	{ 
		private ArmyController m_ArmyController;

		public ArmyAttackTarget( ArmyController controller ) : base ( -1, false, TargetFlags.None ) 
		{ 
         		m_ArmyController = controller; 
		} 

		protected override void OnTarget( Mobile from, object target ) 
		{
			if (  m_ArmyController != null)
			if ( !m_ArmyController.Deleted )
			if (  m_ArmyController.Owner != null )
			if (  m_ArmyController.Owner.Alive && !(m_ArmyController.Owner.Deleted) )
			if (  m_ArmyController.Owner == from )
			if ( target is Mobile)
			{
				m_ArmyController.Attack( from, (Mobile)target );
			}
		}
	}
    ////////////////////////////////////////////////////////
}

In red is my simple method and basehire can be found in the Premium Spawner package here on this forums.

It would be nice if others would post some work here so we can compare, also it might be wise if you do use this method; to add some kind of way for all disbanded members to be removed completely so you don't get a server build up(I just make these basehire npcs spawn in fighters guilds ect).
 

ABTOP

Sorceror
Pyro-Tech;666381 said:
If the recruit button is only available to game master's, then how can players make use of this?? is there a way to allow a charge in gold per soldier recruited so that you can enable this for players??

Or am i misunderstanding the concept here?:confused:
Yeah good idea:)


Dramier thx for translating... Because when i try read this i was confused:eek:
 

Dramier

Wanderer
It would be awesome if you could simply utilize a few of the built-in commands, like "all follow me" and such...

I'm working on that myself, but I haven't played with that part of the RunUO environment yet so it's a learning experience for me.

Well, I've figured out that by removing the && Commandable) section out of the BaseAI I can make the soldiers commandable... which makes it really easy to move them around.
 

Solinari555

Wanderer
loveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveitloveit
Thanks again Alambik, all of your stuff has been spectacular so far! Keep it up!


Big question: I know you run a high-tech server, would you happen to have a gun-type weapon animation?
 

Fixxxer

Sorceror
Has anyone figured it out??

I was just wondering if anyone has figured out how to make it where a player can create an army, I have tried but with no success, also is there a place where you can limit what a character can recuit, an army of dragons or demons seems a bit much.
 
Top